2D-Grafik Fehler beim Laden eines Bildes

poibs

Mitglied
Hallo zusammen,

für die Programmierung eines Spiels, habe ich mit diesem Tutrorial angefangen:

The Java 2D games tutorial

Aber beim Laden eines Bildes bekomme ich diese Exception:

Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:204)
at test.Board.<init>(Board.java:14)
at test.Image.<init>(Image.java:9)
at test.Image.main(Image.java:19)

Dies ist das letzte Beispiel in den Basics (Basics)

Die Bild-Datei ist im package wo die Klassen enthalten sind. Gruß
 
Ordner-Struktur:
/src/test/Board.java
/src/test/image.java
/src/test/landschaft.jpg

Board.java:
Java:
package test;
import java.awt.Graphics;
import java.awt.Graphics2D;

import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Board extends JPanel {
	Image bardejov;

    public Board() {
        ImageIcon ii = new ImageIcon(this.getClass().getResource("landschaft.jpg"));
        bardejov = ii.getImage();
    }

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(bardejov, 10, 10, null); 
    }
    
	private static final long serialVersionUID = 1L;
}

Image.java:
Java:
package test;

import javax.swing.JFrame;


public class Image extends JFrame {

public Image(){
        add(new Board());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(468, 344);
        setLocationRelativeTo(null);
        setTitle("Landschaft");
        setVisible(true);
    }

    public static void main(String[] args) {
        new Image();
    }
    
	private static final long serialVersionUID = 1L;
}
 
liegen die class Dateien im selben Verzeichnis? Oder liegen diese eventuell ein einem Verzeichnis bin/test? Wenn ja, liegt das jpg ebenfalls dort?
 
Hallo zusammen,

habe leider keine Lösung für das obige Problem, aber dafür ein sehr ähnliches.
Auch bei mir wird das Bild nicht korrekt geladen.
Denke ich bin nah an der Lösung.
Vielleicht kann ja jemand helfen.

Java:
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
	
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
	
public class VierGewinntGUI 
{
	private static final long serialVersionUID = 1L;
	private Kino kino;
	private JLabel hinterGrundLabel, spielButtonLabel;	
	private JPanel funktionsEbene, grafikEbene, benutzerEbene;
	
	public VierGewinntGUI()	
	{
		initGUI();
	}
	
	private void initGUI()
	{
		//Fachkonzeptklasse
		kino = new Kino();			   	 				
		
		funktionsEbene = new JPanel();
		funktionsEbene.setSize(600, 600);
		funktionsEbene.setOpaque(false);				
		
		grafikEbene = new JPanel();
		grafikEbene.setSize(600, 600);	    
		grafikEbene.setOpaque(false);
		
		benutzerEbene = new JPanel();
		benutzerEbene.setSize(600, 600);	    
		benutzerEbene.setOpaque(false);	
				
         	JetonBewegung spielerButton = new JetonBewegung ();
		spielerButton.setBounds(200, 400, 108, 107);	
		spielButton.setVisible(true);		
		benutzerEbene.add(spielerButton);		
		
		File spielButtonFile = new File("images/cover/spielButton.jpg");
			
		try
		{
			BufferedImage spielButtonImage = ImageIO.read(spielButtonFile);
			kino.setImage(spielButtonImage);
		} catch (IOException e) {}		
			
				spielButtonLabel = new JLabel(new ImageIcon(kino.getImage()));
				spielButtonLabel.setBounds(100,100,108,107);
				benutzerEbene.add(spielButtonLabel);
				
		File hinterGrundFile = new File("images/cover/hinterGrund.png");
				
		try
		{
			BufferedImage hinterGrundImage = ImageIO.read(hinterGrundFile);
			kino.setImage(hinterGrundImage);
		} catch (IOException e) {}		
		
				hinterGrundLabel = new JLabel(new ImageIcon(kino.getImage()));
				hinterGrundLabel.setBounds(0, 0,600,600);
				grafikEbene.add(hinterGrundLabel);								

		JButton klick = new JButton("Button versetzen");
		klick.setLocation(400, 400);
		klick.addActionListener(new klickBeobachter());
		benutzerEbene.add(klick);

		Mausi mausi = new Mausi();
		spielButtonLabel.addMouseListener(mausi);
		spielButtonLabel.addMouseMotionListener(mausi);					
	}	
	
	public class klickBeobachter implements ActionListener
	{
		public void actionPerformed (ActionEvent e)
		{			
			if(spielButtonLabel.getX()==250 && spielButtonLabel.getY()==175)
			{						
				funktionsEbene.add(spielButtonLabel);
				benutzerEbene.remove(spielButtonLabel);
				spielButtonLabel.setBounds(250, 175, 108, 107);
				
				//JetonBewegung neueBewegung = new JetonBewegung();
				
			}else{System.out.println("Nicht Verschoben");}
		}						
	}
	
	public JPanel gibFunktionsEbene()
	{
		return funktionsEbene;
	}
	
	public JPanel gibGrafikEbene()
	{
		return grafikEbene;
	}
	
	public JPanel gibBenutzerEbene()
	{
		return benutzerEbene;
	}

	public static void main(String[] args) 
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				VierGewinntGUI neueGUI = new VierGewinntGUI();
				
				//Hauptfenster				
				JFrame hauptFenster = new JFrame("Vier Gewinnt - Gewinnst auch du?");
		        hauptFenster.setSize(600, 600);
		        hauptFenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		        hauptFenster.setLocation(300, 70);
		        hauptFenster.setLayout(null);
		        hauptFenster.setVisible(true);
		        hauptFenster.setResizable(false);
		        hauptFenster.add(neueGUI.gibBenutzerEbene());
		        hauptFenster.add(neueGUI.gibGrafikEbene());
		        hauptFenster.add(neueGUI.gibFunktionsEbene());		  
			}
		});				
	}
}

Java:
import java.awt.*;

public class JetonBewegung extends Canvas
{
	static int positionY = 0;
	
	Image spieButtonLabel = getToolkit().getImage("images/cover/spielButton.jpg");

	public void paint(Graphics g) 
	{
		g.drawImage(spieButtonLabel, 10, 10 + positionY, this);
		positionY= positionY + 10;
	}

   public static void main(String[] args) 
   {
      JetonBewegung bewegung = new JetonBewegung();
      /*
      for(int i = 0; i<20; i++)
      {
    	  try {Thread.sleep(30);
    	  	   bewegung.invalidate();
    	  	   bewegung.repaint();}
    	  catch(InterruptedException e) {} 
      }*/
   }
}

lg
Muller
 
Zuletzt bearbeitet:
Danke 😉, die Bild-Datei musste in den Ordner /bin/test/

Ich kenne mich mit der Spiele-Programmierung nicht aus, wenn ihr gute Tutorials für 2D-Prgrammierung in Java kennt, würde ich mir die gerne durchlesen.
 
Hallo zusammen,

habe leider keine Lösung für das obige Problem, aber dafür ein sehr ähnliches.
Auch bei mir wird das Bild nicht korrekt geladen.
Denke ich bin nah an der Lösung.
Vielleicht kann ja jemand helfen.
In diesem Fall muss m.W. die Pfadangabe relativ zum Verzeichnis in dem die Anwendung ausgeführt wird liegen.
Welche Ausgabe liefert:
Code:
System.out.println(spielButtonFile.getAbsolutePath())
und wo liegt das Bild tatsächlich?
 
Also die Pfade stimmen überein.

Das Bild soll auf der obersten Ebene liegen. Diese ist transparent und liegt auf der mit dem schwarzen Bild.
 
Zuletzt bearbeitet:
Noch ein Hinweis: Abgefangen Exception sollte man sich auch ausgeben lassen:
Java:
} catch (IOException e) {
	e.printStackTrace();
}
 
Also die Pfade stimmen überein.

Das Bild soll auf der obersten Ebene liegen. Diese ist transparent und liegt auf der mit dem schwarzen Bild.
Dann gibt es ja keine Probleme mit dem Bilder laden ;-)
Die Bilder werden nicht angezeigt?
Hätte noch ein paar Anmerkungen zum Code:
- AWT und Swing Komponenten nicht gemeinsam verwenden (z.B. JPanel statt Canvas)
- merkwürdig ;-)
- setVisible(true) am JFrame erst aufrufen, nachdem alle Komponenten platziert sind.
- die Kino Klasse... merkwürdig... erst wird das Bild an kino übergeben, um es dann wieder zu holen
- würde ich da ein bisschen mehr Ordnung/Struktur rein bringen
- halte ich eigentlich nicht viel vom Null Layout (für den Zweck meinetwegen)
- werden die Komponenten in umgekehrter Reihenfolge gezeichnet in der sie dem Container hinzugefügt werden
 
Danke schon mal für deine Tipps

Hab schon mal ein paar Sachen am Code eingespart.

Leider kenne ich mich mit Swing usw nicht so gut aus.
Also irgendwie muss ja der Fehler mit den Panels zu tun haben, wenn die Bilder richtig geladen werden.

Hier schon mal mein geänderter Code:
Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
	
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
	
public class VierGewinntGUI 
{
	private static final long serialVersionUID = 1L;
	private JLabel hinterGrundLabel, spielButtonLabel;	
	private JPanel funktionsEbene, grafikEbene, benutzerEbene;
	private BufferedImage spielButtonImage, hinterGrundImage;
	
	public VierGewinntGUI()	
	{
		initGUI();
	}
	
	private void initGUI()
	{	
		funktionsEbene = new JPanel();
		funktionsEbene.setSize(600, 600);
		funktionsEbene.setOpaque(false);				
		
		grafikEbene = new JPanel();
		grafikEbene.setSize(600, 600);	    
		grafikEbene.setOpaque(false);
		
		benutzerEbene = new JPanel();
		benutzerEbene.setSize(600, 600);	    
		benutzerEbene.setOpaque(false);	
				
		ZeichneObjekt spielButton = new ZeichneObjekt();
		spielButton.setBounds(200, 200, 108, 107);		
		benutzerEbene.add(spielButton);
		
		JetonBewegung spielerButton = new JetonBewegung ();
		spielerButton.setBounds(200, 400, 108, 107);	
		benutzerEbene.add(spielerButton);				
		
		File spielButtonFile = new File("images/cover/spielButton.jpg");
			
		try
		{
			spielButtonImage = ImageIO.read(spielButtonFile);
		} catch (IOException e) {e.printStackTrace();}		
			
				spielButtonLabel = new JLabel(new ImageIcon(spielButtonImage));
				spielButtonLabel.setBounds(100,100,108,107);
				benutzerEbene.add(spielButtonLabel);
				
		File hinterGrundFile = new File("images/cover/hinterGrund.png");
				
		try
		{
			hinterGrundImage = ImageIO.read(hinterGrundFile);
		} catch (IOException e) {e.printStackTrace();}		
		
				hinterGrundLabel = new JLabel(new ImageIcon(hinterGrundImage));
				hinterGrundLabel.setBounds(0, 0,600,600);
				grafikEbene.add(hinterGrundLabel);								
				
		JButton klick = new JButton("Button versetzen");
		klick.setLocation(400, 400);
		klick.addActionListener(new klickBeobachter());	
		benutzerEbene.add(klick);

		Mausi mausi = new Mausi();
		spielButtonLabel.addMouseListener(mausi);
		spielButtonLabel.addMouseMotionListener(mausi);		
	}	
	
	public class klickBeobachter implements ActionListener
	{
		public void actionPerformed (ActionEvent e)
		{			
			if(spielButtonLabel.getX()==250 && spielButtonLabel.getY()==175)
			{						
				funktionsEbene.add(spielButtonLabel);
				benutzerEbene.remove(spielButtonLabel);
				spielButtonLabel.setBounds(250, 175, 108, 107);
			}else{System.out.println("Nicht Verschoben");}
		}						
	}
	
	public JPanel gibFunktionsEbene()
	{
		return funktionsEbene;
	}
	
	public JPanel gibGrafikEbene()
	{
		return grafikEbene;
	}
	
	public JPanel gibBenutzerEbene()
	{
		return benutzerEbene;
	}

	public static void main(String[] args) 
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				VierGewinntGUI neueGUI = new VierGewinntGUI();
				
				//Hauptfenster				
				JFrame hauptFenster = new JFrame("Vier Gewinnt - Gewinnst auch du?");
		        hauptFenster.setSize(600, 600);
		        hauptFenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		        hauptFenster.setLocation(300, 70);
		        hauptFenster.setLayout(null);		      
		        hauptFenster.setResizable(false);
		        hauptFenster.add(neueGUI.gibBenutzerEbene());
		        hauptFenster.add(neueGUI.gibGrafikEbene());
		        hauptFenster.add(neueGUI.gibFunktionsEbene());
		        
		        hauptFenster.setVisible(true);
			}
		});				
	}
}
 
Welche Probleme hast Du mit Deinem Programm? Wie äussern diese sich?

Eines Deiner Probleme werden vermutlich auch die LayoutManager der Panels sein.
Diese besitzen per Default ein FlowLayout, d.h. die x, y Werte (setBounds(....)) der Komponenten, die auf den drei Panels platziert werden, werden ignoriert. Vermutlich sollen diese auch keinen LayoutManager verwenden.

Ausserdem würde ich versuchen das ganze stärker zu strukturieren. z.B. die Ebenen in eigene Klassen auszulagern, um da ein bisschen mehr Ordnung und Übersicht in den Code zu bringen.

Dann ist mir in der Klasse JetonBewegung (hoffe Du verwendest jetzt JPanel oder JComponent) noch auf gefallen, dass Du den y Wert (positionY) in der paint (bei JPanel sollte dann paintComponent überschrieben werden) inkrementierst. Das willst Du nicht wirklich, denn Du hast nicht wirklich die Kontrolle darüber wann und wie oft die Methode aufgerufen wird.
 
So habe das Programm erstmal ein bisschen überarbeitet.
Nochmals danke für deine Hilfe bisher.
Hier ist der aktuelle Code

[Java]
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class VierGewinntGUI
{
private static final long serialVersionUID = 1L;
private JPanel funktionsEbene, grafikEbene, benutzerEbene;
private ZeichneObjekt spielJeton;

public VierGewinntGUI()
{
initGUI();
}

private void initGUI()
{
// die Ebenen werden erzeugt und später in vorliegender Reihenfolge im JFrame auf einander liegen
funktionsEbene = new ErzeugeEbene(600, 600, false);
grafikEbene = new ErzeugeEbene(600, 600, false);
benutzerEbene = new ErzeugeEbene(600, 600, false);

JButton klick = new JButton("Button versetzen");
klick.setBounds(0, 0, 100, 100);
klick.addActionListener(new klickBeobachter());
benutzerEbene.add(klick);

ZeichneObjekt hinterGrund = new ZeichneObjekt("images/hinterGrund.png");
hinterGrund.setBounds(0, 0, 600, 600);
grafikEbene.add(hinterGrund);

spielJeton = new ZeichneObjekt("images/spielJeton.jpg");
spielJeton.setBounds(200, 200, 108, 107);
benutzerEbene.add(spielJeton);

JetonDragDrop jetonBewegung = new JetonDragDrop();
spielJeton.addMouseListener(jetonBewegung);
spielJeton.addMouseMotionListener(jetonBewegung);
}

//ActionListener um den Spieljeton von der obersten auf die unterste Ebene zu versetzen
public class klickBeobachter implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if(spielJeton.getX()==250 && spielJeton.getY()==175)
{
funktionsEbene.add(spielJeton);
benutzerEbene.remove(spielJeton);
spielJeton.setBounds(250, 175, 108, 107);
}else{System.out.println("Nicht Verschoben");}
}
}

public JPanel gibFunktionsEbene()
{
return funktionsEbene;
}

public JPanel gibGrafikEbene()
{
return grafikEbene;
}

public JPanel gibBenutzerEbene()
{
return benutzerEbene;
}

public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
VierGewinntGUI neueGUI = new VierGewinntGUI();

//Hauptfenster
JFrame hauptFenster = new JFrame("Vier Gewinnt - Gewinnst auch du?");
hauptFenster.setSize(600, 600);
hauptFenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
hauptFenster.setLocation(300, 70);
hauptFenster.setLayout(null);
hauptFenster.setResizable(false);
hauptFenster.add(neueGUI.gibBenutzerEbene());
hauptFenster.add(neueGUI.gibGrafikEbene());
hauptFenster.add(neueGUI.gibFunktionsEbene());

hauptFenster.setVisible(true);
}
});
}
}
[/Java]


[Java]
import javax.swing.JPanel;

public class ErzeugeEbene extends JPanel
{
private static final long serialVersionUID = 1L;

public ErzeugeEbene(int breite, int höhe, boolean transparenz)
{
setSize(breite, höhe);
setLayout(null);
setOpaque(transparenz);
}
}
[/Java]


[Java]
import java.awt.*;

import javax.swing.JPanel;

public class ZeichneObjekt extends JPanel
{
private static final long serialVersionUID = 1L;
private Image bild;

public ZeichneObjekt(String dateiPfad)
{
bild = getToolkit().getImage(dateiPfad);
}

public void paintComponent(Graphics g)
{
g.drawImage(bild, 0, 0, this);
}
}
[/Java]


[Java]
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;

public class JetonDragDrop extends MouseAdapter implements MouseMotionListener
{
private int startx;
private int starty;
private JComponent c = null;

public void mouseEntered(MouseEvent e)
{
c = (JComponent) e.getSource();
}

public void mousePressed(MouseEvent e)
{
startx = e.getX();
starty = e.getY();
}

public void mouseReleased(MouseEvent e)
{
if(e.getXOnScreen()>=560 && e.getXOnScreen()<= 740 && e.getYOnScreen()>=325 && e.getYOnScreen()<=445)
{
c.setLocation(250, 175);
}
}

public void mouseDragged(MouseEvent e)
{
setPosition(e);
}

private void setPosition(MouseEvent e)
{
int neux = c.getLocation().x + e.getX() - startx;
int neuy = c.getLocation().y + e.getY() - starty;
c.setLocation(neux, neuy);
}

public void mouseMoved(MouseEvent e)
{
}
}
[/Java]


Dein Tip mit dem JPanel anstatt Cavanas oder wie das heißt war genau richtig.
Es ist mir jetzt gelungen die Bilder auf die Ebenen zu zeichnen.

Mein einziges Problem ist jetzt nur noch das der gezeichnete "Hintergrund" auf der mittleren Ebene alle anderen überdeckt.

Habe dir für das bessere Verständnis mal ein Screenshot angehangen.
Der zu sehende Jeton soll über dem schwarzen Bild liegen.

Verstehst du was ich meine?
 

Anhänge

  • VierGewinnt.png
    VierGewinnt.png
    45,4 KB · Aufrufe: 38
;-) Das habe ich schon verstanden. Mir fehlt der Blick auf das große Ganze.

Warum überhaupt die drei Hauptpanels? Da Du eh mit NullLayout arbeitest, warum packst Du nicht alles zusammen auf ein Panel?
 
Ah ok also die ganze Geschichte 😀.

Also ich möchte ein Vier Gewinnt Spiel programmieren.
Die Realisierung habe ich mir wie folg vorgestellt.

Auf die mittlere Grafikebene wird später ein komplettes "Vier Gewinnt" Spielfled gelegt.
Da ich dieses im Moment noch nicht habe ist als Platzhalter erstmal die schwarze Grafik vorhanden.
Auf der obersten Ebene "Benutzerebene" liegen alle Objekte mit denen man interagieren kann.

Die Löcher in der schwarzen Grafik sollen im Moment nur beispielhaft die Löcher des Vier Gewinnt Spielfeldes ersetzen.

Die unterste Ebene ist nun dafür, dass z.B. der Jeton von oben nach unten wandern kann.
Und dabei wird er immer nur sichtbar wenn transparente Stellen in der schwarzen Grafik sind.
 
Nein habe den Jeton nur da jetzt positioniert damit man sieht, dass die schwarze Grafik über der anderen liegt. Und das ist ja auch das Problem. Sie soll unter dem Jeton liegen und nicht wie jetzt über.

12
 
Hab mir den Code ein bisschen genauer angeschaut. Du hast ein Panel benutzerEbene auf dem ist das Bild des Jetons liegt und grafikEbene mit dem schwarzgelöcherten Bild. benutzerEbene müsste nach grafikEbene gezeichnet werden und der Jeton daher oben zu sehen sein.

Und wenn Du erst grafikEbene vor benutzerEbene einfügst hast Du das selbe Bild? Da muss doch sonst noch irgendwas sein/passieren?
 

Zurück
Oben