# Image wird nicht angezeigt?! - MediaTracker/repaint



## Triopoly (15. Jan 2010)

Hallo,
dass ich das letzte mal mit Java gearbeitet habe ist leider schon eine Weile her ... ich versuche momentan einige Bilder mittels Mediatracker in ein JScrollPane einzubinden. Allerdings werden die Bilder nicht angezeigt? Soweit ich das beurteilen kann funzt der MediaTracker aber die update-Methode wird trotz repaint() nicht aufgerufen. Ich denke es ist ein ganz banaler Fehler, der warscheinlich an irgendwelchen mangelnden Grundkentnissen liegt, aber ich komm einfach nicht drauf ... ich hoffe ihr könnte mir weiterhelfen?
Hier erstmal der Quelltext:


```
//imports
import java.awt.*;
import javax.swing.*;

public class Filmstrip extends JScrollPane {

	//constants
	private static final long serialVersionUID = -5318539386368820665L;
	//variable
	private String images[] = { "test1.jpg", "test2.jpg","test3.jpg" };
	private Image[] imgs = new Image[images.length];
	private MediaTracker mt = null;
	// private JLabel imgLabel = new JLabel();

	public Filmstrip() {
		super(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		
		//load images with MediaTracke
		int i;
		mt = new MediaTracker(this);
		for (i = 0; i < images.length; i++) {
			imgs[i] = Toolkit.getDefaultToolkit().getImage(images[i]);
		    mt.addImage(imgs[i], i);
		}//end for
		
		//exception handling
		try {
			mt.waitForAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}//end try/catch
	    if (mt.isErrorID(i)) {
	    	  System.err.println("Couldn't load image file " + images[i]);
		      return;
		}//end if
	    repaint(); 	
	}//end constructor


      public void update(Graphics g) {
              paint(g);
      }
		  
	  public void paint(Graphics g){
		for (int i = 0; i < imgs.length; i++) {
		      g.drawImage(imgs[i], 60, 60, this);
		}
	  }
	
}
```


Anbei noch eine andere Frage. Ich möchte eigentlich möglichst alles in swing programmieren, gibt es dort noch eine "schönere" Möglichkeit Bilder zu laden? 

Ich denke wirklich es liegt an den mangelnden Grundkentnissen und ist ein eigentlich total simlpes Problem ..... 
also schonmal danke im vorraus!!


----------



## SuperSeppel13 (15. Jan 2010)

Hast du dir schonmal das Zeichnen in Swing Tutorial (hier im Forum) durchgelesen?
In Swing wird grundsätzlich paintComponent überschrieben, um darin zu zeichnen.

Bilder laden kann man am einfachsten mit ImageIO.read(*someFile/Filename*).

Außerdem musst du der JScrollPane ja auch irgendeine Komponente hinzufügen, die dann gescrollt wird.
Am besten zeichenest du das Bild auf ein JPanel, dem du dann die Größe des Bildes gibst und es in die JScrollPane einbettest.


----------



## Michael... (15. Jan 2010)

- überschreibe nicht update
- in Swingkomponenten paintComponent anstelle von paint überschreiben
- überschreibe nicht die paint... von ScrollPane, sondern nimm ein JPanel oder JComponent und füge diese in die ScrollPane ein


----------



## Triopoly (15. Jan 2010)

Erstmal vielen Dank für die schnelle Antwort! 
Habe es jetzt geändert, aber die Bilder werden immer noch nicht angezeigt? 


```
//imports
import java.awt.*;
import javax.swing.*;

public class Filmstrip extends JScrollPane {

	//constants
	private static final long serialVersionUID = -5318539386368820665L;
	//variable
	private String images[] = { "test1.jpg", "test2.jpg","test3.jpg" };
	private Image[] imgs = new Image[images.length];
	private MediaTracker mt = null;
	private JPanel imgPanel = new JPanel();

	public Filmstrip() {
		super(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		setSize(599,500);
	
		//load images with MediaTracke
		int i;
		mt = new MediaTracker(imgPanel);
		for (i = 0; i < images.length; i++) {
			imgs[i] = Toolkit.getDefaultToolkit().getImage(images[i]);
		    mt.addImage(imgs[i], i);
		}//end for
		
		//exception handling
		try {
			mt.waitForAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}//end try/catch
	    if (mt.isErrorID(i)) {
	    	  System.err.println("Couldn't load image file " + images[i]);
		      return;
		}//end if
	    imgPanel.setSize(60,200);
	    imgPanel.repaint(); 	
	    setViewportView(imgPanel);
	}//end constructor


      public void update(Graphics g) {
    	  System.out.print("update");
    	  paintComponent(g);
      }
		  
	  public void paintComponent(Graphics g){
			for (int i = 0; i < imgs.length; i++) {
		      g.drawImage(imgs[i], 60, 60, imgPanel);
			}
	  }
	

}
```

Bin mir auch nicht ganz sicher, wenn ich paintComponent() verwende, muss ich dann die update Methode noch überschreiben? Oder reicht es wenn ich einfach repaint() aufrufe? Wie auch immer, paintComponent() wird nicht ausgeführt. Woran kann das liegen?

Das Tutorial hatte ich mir angeschaut und auch hier etwas im Forum und im Inet rumgesucht, aber ich finde keinen Unterschied zwischen den anderen (scheinbar funktionierenden Beispielen) und meinem ... 

Edit:
Ach ja, noch etwas, Würde ich ImageIO dann anstelle von Toolkit.getDefaultToolkit().getImage() verwenden?


----------



## Michael... (15. Jan 2010)

Nicht die paintComponent der JScrollPane überschreiben!!
Hier mal ein Bsp. mit einem selbst gemalten Bild (man kann natürlich auch ein Bild von Filesystem verwenden).

```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;

public class DrawImageDemo extends JFrame {
	
	public DrawImageDemo() {	
		this.getContentPane().add(new JScrollPane(new PaintPanel()), BorderLayout.CENTER);
	}
	
	class PaintPanel extends JComponent {
		private BufferedImage image;
		
		public PaintPanel() {
			this.image = DrawImageDemo.createImage();
			this.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
		}
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
		}
	}
	
	public static BufferedImage createImage() {
		BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = image.createGraphics();
		int[] x = new int[] { 10, 25, 50, 75, 100, 125, 150, 175 };
		int[] y = new int[] { 10, 50, 30, 80, 80, 65, 85, 150 };
		for (int i = 1; i < Math.min(x.length, y.length); i++)
			g.drawLine(x[i - 1], y[i - 1], x[i], y[i]);
		g.dispose();
		return image;
	}

	public static void main(String[] args) {
		JFrame frame = new DrawImageDemo();
		frame.setBounds(0, 0, 150, 150);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
```


----------



## Triopoly (15. Jan 2010)

Hab es jetzt nach deinem Beispiel geändert, aber es funzt immer noch nicht ;(
Wobei dein Beispiel als solches funktioniert  Liegt also an meinen Änderungen ... 
Aber immerhin springt er jetzt schonmal ins paintComponent() rein!



```
//imports
import java.awt.*;
import javax.swing.*;

public class Filmstrip extends JScrollPane {

	//constants
	private static final long serialVersionUID = -5318539386368820665L;
	//variable

	static JPanel imagePanel =  new Filmstrip().new ImagePanel();
	public Filmstrip() {
		super(imagePanel ,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		setSize(599,500);
		setViewportView(imagePanel);
	}//end constructor


	class ImagePanel extends JPanel {
		  String images[] = { "test1.jpg", "test2.jpg","test3.jpg" };
		  Image[] imgs = new Image[images.length];
		  MediaTracker mt = null;
	        
		  public ImagePanel() {
			  
			  	int i;
	    		mt = new MediaTracker(this);
	    		for (i = 0; i < images.length; i++) {
	    			imgs[i] = Toolkit.getDefaultToolkit().getImage(images[i]);
	    		    mt.addImage(imgs[i], i);
	    		}//end for
	    		
	    		//exception handling
	    		try {
	    			mt.waitForAll();
	    		} catch (InterruptedException e) {
	    			e.printStackTrace();
	    		}//end try/catch
	    	    if (mt.isErrorID(i)) {
	    	    	  System.err.println("Couldn't load image file " + images[i]);
	    		      return;
	    		}//end if
			  
		  }
		
		  protected void paintComponent(Graphics g) {
		    super.paintComponent(g);
		       	int x,y,i;
		    for (i = 0; i < imgs.length; i++) {
		       x = imgs[i].getHeight(null);
		       y = imgs[i].getWidth(null);
		    	g.drawImage(imgs[i], x, y, this);
		     //  x += imgs[i].getWidth(null);
		    }
		    System.out.println("--paintComponent--");
		  }
	
	}

}
```


----------



## Ebenius (17. Jan 2010)

Erstmal ganz trivial: Sicher, dass die Datei [c]test1.jpg[/c] existiert und lesbar ist? Gib mal in Zeile 26 aus: [java=26]System.out.printf("%s readable: %b", new File(images[0]).getAbsolutePath(), new File(images[0]).canRead());[/code]

Auch wenn's mit dem Problem nix zu tun hat: Zeile 12 ist ganz böse: [java=12]static JPanel imagePanel =  new Filmstrip().new ImagePanel();[/code]
Mach die innere Klasse ImagePanel [c]static[/c], wenn Du sie schon in einem statischen Kontext brauchst -- was hier auch gar nicht der Fall ist. ;-)

Ebenius


----------



## Michael... (19. Jan 2010)

Ich hab jetzt nirgends gesehen, dass die PreferredSize des ImagePanel gesetzt wird --> Wird das Panel überhaupt angezeigt? Vielleicht mal eine Border drum rum zeichnen oder Hintergrund einfärben (setOpaque(true) nicht vergessen).

Ausserdem  in Zeile 51 bis 53 enhalten x und y die Breite und Höhe des Bildes. Ist das so beabsichtigt? Je nach dem wie gross die Bilder sind, könnte es sein, dass sie ausserhalb des sichtbaren Bereich des Panels gezeichnet werden.


Triopoly hat gesagt.:


> [JAVA=47]
> protected void paintComponent(Graphics g) {
> super.paintComponent(g);
> int x,y,i;
> ...


----------



## Triopoly (20. Jan 2010)

@Ebenius 
Es gab tatsächlich ein Problem beim Laden der Bilder, der Pfad wurde nicht richtig aufgelöst ... das Problem ist aber nun behoben und die Bilder werden in das Panel geladen und auch angezeigt.
Die Innere Klasse habe ich nun ausgelagert, also existiert die "böse Zeile" auch nicht mehr 

@Michael
Ich hatte wirklich vergessen PreferredSize zu setzen, danke! 

Nun scheint es alles zu funktionieren. Hier mal meine Lösung:

Das ScrollPanel:

```
//imports
import java.awt.*;
import javax.swing.JScrollPane;


public class Filmstrip extends JScrollPane{
	//constants
	private static final long serialVersionUID = -5318539386368820665L;
	//variable
	static ImagePanel imagePanel = new ImagePanel();
	
	public Filmstrip() {
		super(imagePanel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		this.setSize(new Dimension(imagePanel.getPreferredSize()));
		setViewportView(imagePanel);
		//getVerticalScrollBar().setUnitIncrement(10);
		this.setVisible(true);
	}//end constructor

}//end class Filmstrip
```

Und das JPanel:


```
//imports
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class ImagePanel extends JPanel {
	
	//constants
	private static final long serialVersionUID = -2131260547040151442L;
	//variable
	private String images[] = {"src/Dokumentationstool/bla1.jpg", "src/Dokumentationstool/bla2.jpg","src/Dokumentationstool/bla3.jpg"};
	private BufferedImage[] imgs = new BufferedImage[images.length];
	private MediaTracker mt = new MediaTracker(this);
	
	public ImagePanel(){
		int index;
   		for (index = 0; index < images.length; index++) {
   			try {
   				imgs[index] = ImageIO.read(new File(images[index]));
			} catch (IOException e) {
				e.printStackTrace();
			}//end try-catch
	    	mt.addImage(imgs[index], index);
	    }//end for
	    		
	   	//exception handling
	    try {
	    	mt.waitForAll();
	    } catch (InterruptedException e) {
	    	e.printStackTrace();
	    }//end try-catch
	    if (mt.isErrorID(index)) {
	    	System.err.println("Couldn't load image file " + images[index]);
	    	return;
	    }//end if
	    
	    this.setBorder(new LineBorder(Color.BLACK));
	    //this.setOpaque(true);
	    //this.setVisible(true);
	    this.setPreferredSize(new Dimension((imgs.length * 80),80));
	    this.setSize(this.getPreferredSize());	  
   	}//end constructor

   	protected void paintComponent(Graphics g) {
   		super.paintComponent(g);
    	int width = 0;
		for (int i = 0; i < imgs.length; i++) {
			g.drawImage(imgs[i], width, 0, this);
			width += imgs[i].getWidth();
		}//end for
   	}//end paintComponent()
}//end class ImagePanel
```

Noch einmal vielen, vielen Dank für die Hilfe!!
Ich hab schon ewig nicht mehr mit Java gearbeitet und daher einfach eine Menge an Grundlagen vergessen (leider!). Falls euch also im Quelltext noch etwas auffällt was man so nicht machen sollte, wäre es lieb wenn ihr mir bescheid gebt. Danke!
Ansonsten ist das Thema wohl hoffentlich entgültig erledigt!


----------



## Ebenius (20. Jan 2010)

Anmerkungen:

Ich hab noch nie mit ImageIO gearbeitet, daher bin ich nicht ganz sicher. Aber ich glaube zu wissen, dass Du keinen MediaTracker benötigst, weil ImageIO die Bilder stets vollständig läd.

Der Form halber zu nennen: [java=30]        try {
            mt.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
            // When InterruptedException is thrown, the flag is cleared. Reset it, to
            // give our caller the chance to react properly
            Thread.currentThread().interrupt();
        }//end try-catch[/code]

Standard-Rahmen erzeugt man normaler Weise mit der [c]BorderFactory[/c]. Nicht dass das einen Unterschied machen würde ... ;-)

Ansonsten sieht's doch gut aus; auch wenn ich mich nie mit der [c]// this is the end of something[/c]-Notation anfreunden können werde. :-D

*(Edit) Nachtrag:*
[java=14]private String images[] = {"src/Dokumentationstool/bla1.jpg", "src/Dokumentationstool/bla2.jpg","src/Dokumentationstool/bla3.jpg"};[/code]
Das ist seltsam. So wird Dein Code wahrscheinlich außerhalb der IDE nie laufen. Ist [c]Dokumentationstool[/c] ein Package? Dann sollte es klein geschrieben werden. Und dann kann man super per [c]Class.getResource(...)[/c].

Ebenius


----------

