Input/Output ImageIO kommt mit pic_url nicht klar

Reggi

Mitglied
Hallo zusammen,

ich bin gerade fleißig an Quaxlis Tutorial dran. Doch irgendwie muss ich was falsch gemacht haben :autsch:.
Ich bin an der Stelle, wo eigentlich das Fenster mit dem animierten Hubschrauber sein sollte.
Aber aus irgendeinem Grund gibt er eine IOException aus, die sich auf die Bild-URL bezieht. Fehlermeldung wie folgt:

Code:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
	at javax.imageio.ImageIO.read(ImageIO.java:1388)
	at spiel.SpielFeld.loadPics(SpielFeld.java:127)
	at spiel.SpielFeld.doInitializiations(SpielFeld.java:47)
	at spiel.SpielFeld.<init>(SpielFeld.java:38)
	at spiel.SpielFeld.main(SpielFeld.java:26)

Jetzt hab ich den Pfad überprüft und am Anfang hatte ich aus versehen einen falschen Ordner angegeben, weil ich nicht bedacht hab, dass ja jede IDE andere Bezeichnungen benutzt war also logisch. Aber jetzt lädt er die Bilder immernoch nicht. ;(
Hier mal die Klasse:
Java:
package spiel;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ListIterator;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SpielFeld extends JPanel implements Runnable {
    private static final long serialVersionUID = 1L;
    JFrame frame;
    long delta = 0;             //Berechnung der Zeit, die für den letzten Durchlauf benötigt wurde
    long last = 0;              //Speicherung der letzten Systemzeit
    long fps = 0;               //für Errechnung der FPS
    Sprite copter;
    Vector<Sprite> actors;
    Vector<Sprite> painter;
    
    public static void main (String [] args) {
        new SpielFeld (800,600);
    }
    
    //Fenster fürs Spiel erstellen
    public SpielFeld(int w, int h) {
        this.setPreferredSize(new Dimension(w,h));
        frame = new JFrame("Spieldemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.pack();
        frame.setVisible(true);
        
        doInitializiations();
        
        Thread th = new Thread(this);
        th.start();
    }
    
    private void doInitializiations() {
        last = System.nanoTime();
        
        BufferedImage[] heli = loadPics("pics/heli.gif", 4);
        
        actors = new Vector<Sprite>();
        painter = new Vector<Sprite>();
        copter = new Sprite(heli,400,300,100,this);
        actors.add(copter);
    }
    
    //Gameloop
    @Override
    public void run() {
        while(frame.isVisible()) {
            computeDelta();                          //Methode zur Zeitberechnung
            
            //Methoden für die Spiellogik
            checkKeys();
            doLogic();
            moveObjects();
            cloneVectors();
            
            repaint();
            
            try {
                Thread.sleep(10);
            } catch ( InterruptedException e) {}
        }
    }
    
    @SuppressWarnings("unchecked")
    private void cloneVectors() {
        painter = (Vector<Sprite>) actors.clone();
    }
    
    private void computeDelta() {
        delta = System.nanoTime() - last;           //Errechnen der zeit für den Schleifendurchlauf in Nanosek
        last = System.nanoTime();                   //Speicherung der Aktuellen Systemzeit
        fps = ((long) 1e9/delta);                   //Errechnung der Framerate
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        g.setColor(Color.red);
        g.drawString("FPS: " + Long.toString(fps), 20, 10);
        
        if (painter != null) {
            for (ListIterator<Sprite> it = painter.listIterator(); it.hasNext();) {
                Sprite r = it.next();
                r.drawObjects(g);
            }
        }
    }

    private void checkKeys() {
        
    }

    private void doLogic() {
        for(ListIterator<Sprite> it = actors.listIterator(); it.hasNext();) {
            Sprite r = it.next();
            r.doLogic(delta);
        }
    }

    private void moveObjects() {
        for(ListIterator<Sprite> it = actors.listIterator(); it.hasNext();) {
            Sprite r = it.next();
            r.move(delta);
        }
    }
    
    private BufferedImage[] loadPics(String path, int pics) {
        BufferedImage[] anim = new BufferedImage[pics];
        BufferedImage source = null;
        
        //URL pic_url = getClass().getResource("/pics/heli.gif");
        URL pic_url = getClass().getClassLoader().getResource(path);
        
        try {
            source = ImageIO.read(pic_url);
        } catch (IOException e) {}
        
        for(int x = 0; x < pics; x++) {
            anim[x] = source.getSubimage(x*source.getWidth()/pics, 0, source.getWidth()/pics, source.getHeight());
        }
        
        return anim;
    }
}

Irgendwas was ich übersehen hab oder findet er vllt einfach den path nicht?
 
Also eine URL musst du natürlich absolut angeben, da läuft nix mit relativer Pfadangabe. Wenn du in den browser /index.html eingibst kommst du ja auch nicht auf deine wunschseite.
 
Naja ich dachte eigentlich, dass das mit dem path so ist wie beim HTML, dass der einfach den Pfad relativ zur .class nimmt. Da muss ich ja auch nicht jedesmal den ganzen Pfad angeben. Und der Pfad muss dann in die
Java:
BufferedImage[] heli = loadPics("pics/heli.gif", 4);
?
 
Schaut nicht so schlecht aus. Wobei es generell ne schlechte Idee ist bilder in den build ordner zu legen. Bei nem clean wird der kommentarlos geleert 🙂

Ich erstelle mir immer einen zusätzlichen source Folder der in der Regel resources heißt. In dem liegen dann alle Grafiken oder andere resource dateien. Da lässt sich dann einfach mit nem absoluten pfad drauf zugreifen (/images/image.png). Vielleicht hilft dir folgender link weiter:
Grafikdateien laden und anzeigen ? Byte-Welt Wiki
 
Und wenn ich das richtig verstehe reicht als absoluter Pfad alles von Spiel/... abwärts aus?
Weil wenn jemand anders jetzt mein Spiel hätte oder es fertig hab und als Programm starte dann kann es sich ja auch woanders als in dem Laufwerk sein, wo ich es jetzt habe.
 
Also ich hab jetzt nochmal alles durchgeschaut und zumindest verstanden wie alles zusammenhängt.
Nun mal meine Gedanken dazu:

Java:
private BufferedImage[] loadPics(String path, int pics) {
        BufferedImage[] anim = new BufferedImage[pics];
        BufferedImage source = null;
        
        URL pic_url = getClass().getClassLoader().getResource(path);
        
        try {
            source = ImageIO.read(pic_url);
        } catch (IOException e) {}
        
        for(int x = 0; x < pics; x++) {
            anim[x] = source.getSubimage(x*source.getWidth()/pics, 0, source.getWidth()/pics, source.getHeight());
        }
        
        return anim;
Das ist die Methode, die das Bild laden soll und in ein BufferedImage Array stecken und nach einander aufrufen soll.
Sie erwartet die Parameter String path (das wäre dann also die Pfadangabe) und int pics (die Anzahl von Bildern im Array).

Den wichtigsten Parameter um den es hier geht bekommt die Methode über:
den Aufruf von:

Java:
BufferedImage[] heli = loadPics("heli.gif", 4);

@EikeB: Der Link war eigentlich ganz gut, allerding weiß ich wirklich nicht weiter, weil egal was ich angebe es ändert sich nichts.
Dann ist mir noch die erste Zeile der Fehlermeldung ins Auge gestoßen.
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
Was ja eigentlich die Exception ist, die Quaxli mit
Java:
        if (painter != null) {
            for (ListIterator<Sprite> it = painter.listIterator(); it.hasNext();) {
                Sprite r = it.next();
                r.drawObjects(g);
            }
        }
verhindern wollte. Mit anderen Worten nochmehr ??? über meinem Kopf und was ich jetzt noch gefunden hab ist ein Tread:
http://www.java-forum.org/spiele-multimedia-programmierung/125480-probleme-beim-laden-images-tutorial-fuer-java-spiele.html
Da wird dieses Problem schon einmal behandelt und ich dachte grad hey cool endlich die Lösung.
Also hab ich die .getClassLoader() rausgenommen den kompletten Pfad in der loadPics Methode angegeben und....
es geht immernoch nicht ;(.

Weiß jemand einen Rat?
 
Hallo zusammen,
nach einigen Tagen drüber schlafen und mich mit anderen Sachen beschäftigen hat geholfen.
Keine Ahnung, was er an der von Quaxli vorgeschlagenen pic/heli.gif auszusetzen hatte, auf jeden Fall hab ich den Ordner mit resources wieder in den .class -Ordner gezogen den Pfad auf
Java:
BufferedImage[] heli = loadPics("resources/heli.gif", 4);
zurückgeändert und aufeinmal gehts :bahnhof:.
Wer weiß vllt hat er einfach irgendwas gehabt, wo man das Programm einfach neustarten musste. Danke auf jeden Fall EikeB für die nette Hilfe. Dein Link hat mir geholfen.

Ach und für alle Mitneulinge es gibt da ne ganz tolle Exception, die man sich vllt mit dazubauen sollte, dann weiß man wirklich wo der Fehler herkommt:

Java:
catch (IllegalArgumentException iae) {
            JOptionPane.showMessageDialog (this, 
            "Das Bild konnte nicht gefunden werden!",
            "java.lang.IllegalArgumentException",
            JOptionPane.ERROR_MESSAGE);
}

Und bei der IOException das gleiche mit konnte nicht geladen werden und schon sieht man besser wo der Fehler liegt. Ich hoffe das hilft einigen weiter. 🙂
 

Zurück
Oben