# Warum wird das Bild nicht angezeigt?



## Fjoergyn (4. Dez 2006)

Das Teil soll ein ausgewähltes Bild anzeigen. Nachdem ich die Datei ausgewählt habe passiert nix weiter. Wo ist mein Fehler?


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
 
public class AppletASP extends JApplet implements ActionListener
{
	JButton button1 = new JButton();
	boolean successful=true;
	JOptionPane jop = new JOptionPane();
	private File picture;
	String pfad;
 
	public void init()
	{
		button1.setLabel("lala");
		this.getContentPane().add(button1, BorderLayout.NORTH);
		button1.setBounds(120,200,98,30);
		button1.addActionListener(this);
 
	}
	public void paintImage( Graphics g ) {

	Image image = Toolkit.getDefaultToolkit().getImage( pfad );
	g.drawImage(image,0,0,this);	

	}

	public void actionPerformed(ActionEvent ae)
	{
		if(ae.getSource().equals(button1))
		{

					JFileChooser fileDialog = new JFileChooser();
					int xx = fileDialog.showSaveDialog(this);
					fileDialog.show();
					switch(xx) {
       					  case JFileChooser.APPROVE_OPTION:
          					picture = fileDialog.getSelectedFile();
						//ImageIcon icon = new ImageIcon(picture.getAbsolutePath());
						pfad = picture.getAbsolutePath();
						

						

                 			}
 
		}

	
	}


	

	
}
```


----------



## L-ectron-X (4. Dez 2006)

Applets benutzen im Gegensatz zu Applikationen nicht das Toolkit um Bilder zu laden. Die Klasse Applet hat eine eigene _getImage()_-Methode, die verwendet werden muss.
Und das Bild solltest du dann in der paint()-Methode zeichnen. Also brauchst du dazu nur deine paintImage()-Methode umbenennen. Um das Bild zu laden ist dann aber die paint()-Methode ein denkbar ungünstiger Ort. Sowas ist gut in der init()-, start()-, oder einer Event-Methode untergebracht.


----------



## Fjoergyn (4. Dez 2006)

OK...nur will getImage unbedingt ne URL ... wie schaff ich es das es auch einen Pfad schluckt? Ich will in meinem Applet ja ein lokales Bild anzeigen lassen ... nur Blick ich da einfach nicht durch: getImage im Toolkit nimmt einen String an, geht aber nicht bei Applets ...  getImage aus AppletContext nimmt nur URLs an ... er muss doch ne Möglichkeit geben lokale Bilder in nem Applet anzuzeigen .. deswegen signiere ichs ja auch: Damit es eben lokalen Zugriff hat! Wenn das Bild auf nem Server wäre, dann wärs ein Kinderspiel, aber so ...  :bahnhof: 

*Verzweifel* 

Ach ja und noch was: Wird die paint()-Methode automatisch aufgerunfen? Denn in allen Beispielen die ich bisher gesehn hab wird sie nicht explizit aufgerufen. Aber wie stelle ich sicher das sie erst aufgerufen wird wenn ich ein Bild ausgewählt habe?


----------



## L-ectron-X (5. Dez 2006)

Fjoergyn hat gesagt.:
			
		

> getImage aus AppletContext nimmt nur URLs an




```
private Image image;
...

File file = chooser.getSelectedFile();
try {
   image = getImage(file.toURL());
}
catch(MalformedURLException e) {
   System.out.println("Fehlerhafter URL:\n"+e.getMessage());
}
```
Probiere es mal so.



			
				Fjoergyn hat gesagt.:
			
		

> Ach ja und noch was: Wird die paint()-Methode automatisch aufgerunfen?
> ...
> Aber wie stelle ich sicher das sie erst aufgerufen wird wenn ich ein Bild ausgewählt habe?


Ja, die paint()-Methode wird von der VM aufgerufen, den Zeitpunkt kannst du mit repaint() beeinflussen.
Wenn du also ein Bild geladen hast, rufst du repaint() auf.

Und meine Aussage oben ist noch etwas zu allgemein. Du schreibst ein JApplet, dort muss nicht die paint()-Methode sondern die paintComponent()-Methode überschrieben werden.
Die Anweisungen bleiben aber ansonsten gleich.
Und: die erste Anweisung in der paintComponent()-Methode sollte immer
	
	
	
	





```
public void paintComponent(Graphics g) {
   super.paintComponent(g);
...
}
```
sein.


----------



## Fjoergyn (5. Dez 2006)

Super das du um die Zeit noch antwortest  dickes danke

Edit:
Der Code schaut nun so aus:



```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.lang.*;
import java.net.*;

 
public class AppletASP extends JApplet implements ActionListener
{
	JButton button1 = new JButton();
	boolean successful=true;
	JOptionPane jop = new JOptionPane();
	private File picture;
	String pfad;
	private Image image;

 
	public void init()
	{
		button1.setLabel("Datei");
		this.getContentPane().add(button1, BorderLayout.NORTH);
		button1.setBounds(120,200,98,30);
		button1.addActionListener(this);
 
	}

	public void paintComponent( Graphics g ) {
		super.paintComponent(g);
		g.drawImage(image,0,0,this);	

	}

	public void actionPerformed(ActionEvent ae)
	{
		if(ae.getSource().equals(button1))
		{

					JFileChooser fileDialog = new JFileChooser();
					int xx = fileDialog.showSaveDialog(this);
					fileDialog.show();
					switch(xx) {
       					  case JFileChooser.APPROVE_OPTION:
          					picture = fileDialog.getSelectedFile();
						//pfad = picture.getAbsolutePath();						
						try {
   							image = getImage(picture.toURL());
						}
						catch(MalformedURLException e) {
   							System.out.println("Fehlerhafter URL:\n"+e.getMessage());
						}
						repaint();
                 			}
		}
	}

}
```


Nun krieg ich folgenden Error:

AppletASP.java:30 Cannot find symbol
symbol : method paintComponent(java.awt.Graphics)
location: class javax.swing.JApplet
..............super.paintComponent(g);
.................... ^


Hatte noch n anderen Error den ich aber mit google lösen konnte, aber an dem beiß ich mir echt grad die Zähne aus ... an fehlenden importen kann es nicht liegen ... 
Ich hab die Zeile mal auskommentiert und das Applet getestet, und es geschah nix ... liegt das nun an der fehlenden Zeile oder ist da was anders faul?
In den APPROVE_OPTION sprinmgt er doch rein, oder?


----------



## L-ectron-X (5. Dez 2006)

Ups, sorry. War mein Fehler. War wohl doch schon etwas spät (früh) heute...

JApplet ist keine JComponent, sondern erbt direkt von Applet. Und Applet kennt nun mal keine paintComponent()-Methode.
*paint(Graphics g)* war schon richtig!

Aber ich sehe schon das nächste Problem auf dich zu kommen...
Beim Start des Applet dürfte eine NullPointerException geworfen werden, weil die VM bereits die paint()-Methode aufruft, die ja das Bild zeichnen soll. Aber es existiert zu diesem Zeitpunkt noch gar kein Image-Objekt, das gezeichnet werden könnte. Hier musst du also noch auf _null_ prüfen.

Und weil wir schon dabei sind, wirds dann auch schon das nächste Problem geben...
Die paint()-Methode zeichnet die gesamte Appletfläche neu. Das heißt, dein angezeigtes Bild wird alle GUI-Komponenten überzeichnen. Du kannst also u.U. den Button zum Öffnen des JFileChoosers nicht mehr sehen.
Abhilfe schafft hier entweder die Implementierung eines eigenen JPanels, von dem du die paintComponent()-Methode entsprechend überschreibst, oder der Einsatz eines JLabels auf dem du das Bild mit
	
	
	
	





```
label.setIcon(new ImageIcon(image));
```
zeichnen lässt.
Das JLabel bzw. dein eigenes JPanel fügst du dann dem CENTER-Bereich (BorderLayout) deines Applets hinzu.

Möglicherweise sind aber die Bilder größer als der nutzbare Anzeigebereich. Abhilfe könnte der Einsatz einer JScrollPane bringen, oder die Skalierung des Bildes auf die passende Größe.


----------



## Fjoergyn (5. Dez 2006)

THX ... endlich geschafft. Habs mit einem JLabel gemacht. Wenn ich jetzt allerdings n zweiten Button hinzufüge, reagiert der ActionListener nicht mehr auf den ersten obwohl alles gleich bleibt  ???:L

Falls dus dir ma angucken willst:
http://weltenreich.awardspace.com/

Endlich fertig     :toll:  :applaus:


----------



## L-ectron-X (5. Dez 2006)

Naja, in deinem Code sind schon noch einige Fehler...


----------



## Fjoergyn (6. Dez 2006)

Zum Beispiel? Wenn alles funktioniert fällt es mir, als Neuling, schwer einen Fehler zu Finden.
Den aktuellen Code findest du hier: 
http://weltenreich.awardspace.com/Applet.txt


----------



## L-ectron-X (8. Dez 2006)

Zum Beispiel...

...nicht benötigte Objekte und Variablen aus dem Quelltext entfernen,

außerdem Referenzvergleich

```
if(ae.getSource().equals(button1)) //nicht so
if(ae.getSource() == button1) //sondern so
```

und den JFileChooser bereits in der init()-Methode erzeugen. So steht er nach Button-Klick sofort zur Verfügung, es wird nicht jedesmal ein neues Objekt erzeugt und es steht immer das Verzeichnis der letzten Auswahl zur Verfügung.

Die setBounds()-Methoden bewirken in einem BorderLayout absolut nichts. (Raus damit!)

Instanzvariablen _privat_ deklarieren!

Das Paket _java.lang_ wird standardmäßig vom Compiler importiert, das brauchst du nicht machen.
Das Paket _javax.imageio_ brauchst du hier nicht. (Raus damit!)

Die Anweisung
	
	
	
	





```
fileDialog.show();
```
ist überflüssig. (Raus damit!)


----------

