# Bilder in GUI ändern ohne repaint()



## bob_sheknowdas (25. Mai 2012)

Hallo,

ich habe mit java3D ein Spiel programmiert und wollte das in eine GUI packen, die mir zusätzlich zum eigentlichen 3D-Spielbildschirm auch ein paar Statuswerte anzeigt. 
Dazu gehört unter anderem ein Bild (png) der aktuell gezogenen Waffe.
Nun soll natürlich dieses Bild auch wechseln, wenn die Waffe gewechselt wird.

Bisher habe ich dafür die Methode setIcon() genutzt. Die führte aber zu den unschönen Effekt, dass bei Bildänderung die ganze GUI (also auch mein 3D-Spielbildschirm) kurz flackert (hätte nur das Panel, welches das waffen.png enthällt geflackert wäre das kein Problem).
Ich nehme stark an, das Flackern kommt dadurch zu stande, dass setIcon() auch repaint() aufruft, sicher bin ich mir aber nicht.

Ich habe jetzt nach Alternativlösungen gesucht. Die einzige Idee, die mir soweit gekommen ist, war mehrere Panels von vorneherein mit den Bildern auszustatten und dann während der Laufzeit bei Bedarf einfach das aktuelle Panel aus der GUI zu löschen und durch das mit dem korekkten Bild zu ersetzen.
Das hat aber so richtig auch nciht funktioniert...



Hat von euch vllt jemand eine andere Idee wie ich das umsetzen könnte?
Für jegliche Hilfe wie immer vielen Dank im Vorraus.


----------



## Fu3L (25. Mai 2012)

setIcon() rufst du wo auf? Auf einem JLabel? 
Dann könntest du tatsächlich deine verschiedenen JLabels einem Panel hinzufügen und immer wechseln. Dann rufst du nur panel.repaint() auf. Vllt funktioniert das, bin gespannt^^


----------



## bob_sheknowdas (25. Mai 2012)

Fu3L hat gesagt.:


> setIcon() rufst du wo auf? Auf einem JLabel?
> Dann könntest du tatsächlich deine verschiedenen JLabels einem Panel hinzufügen und immer wechseln. Dann rufst du nur panel.repaint() auf. Vllt funktioniert das, bin gespannt^^



Zu den ersten beiden Fragen  -  meine Klasse sieht kurz gefasst so aus:


```
public class GUI extends JFrame{

	private final Spiel parent;
	private JLabel cw;
	private ImageIcon weapon1;
	private ImageIcon weapon2;

	public GUI(Spiel spiel){
		parent=spiel;
		ladeBilder();
		cw = new JLabel(weapon1);
		add(parent);
		add(cw);
		pack();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}

	private void ladeBilder() {
		    weapon1 = new ImageIcon("src/MainPackage/Weapon1.png");
		    weapon2 = new ImageIcon("src/MainPackage/Weapon2.png");
	}

	private void updateGUI() {
		if(parent.getFlugzeug().getSchussart()==1) cw.setIcon(weapon1);
		else if(parent.getFlugzeug().getSchussart()==2) cw.setIcon(weapon2);
		
	}
```

Wie gesagt, deinen Vorschlag habe ich schonmal getestet, das hat aber nicht hingehauen.
Vllt könntest du mir in einem kurzem Codebeispiel zeigen wie du das genau meinst?


----------



## Fu3L (25. Mai 2012)

Pack mal das JLabel auf ein extra Panel. Also du fügst ein Panel zur GUI hinzu anstelle des Labels und dann die Labels immer auf dieses extra Panel. Wenn du nun für dieses Panel repaint() aufrufst könnte es sein, dass der Rest ausgespart wird.


----------



## Marco13 (25. Mai 2012)

Das setIcon müßte wohl auch mit SwingUtilities auf dem EDT gemacht werden, falls das nicht schon durch einen Buttonklick oder so ausgelöst wird. Ansonsten... beschreibe mal das "Flackern" genauer... die Kristallkugel in meinem Bauch sagt: Füg' mal in der main als erste Zeile
System.setProperty("sun.awt.noerasebackground", "true");
ein... aber die irrt sich auch manchmal


----------



## bob_sheknowdas (29. Mai 2012)

Fu3L hat gesagt.:


> Pack mal das JLabel auf ein extra Panel. Also du fügst ein Panel zur GUI hinzu anstelle des Labels und dann die Labels immer auf dieses extra Panel. Wenn du nun für dieses Panel repaint() aufrufst könnte es sein, dass der Rest ausgespart wird.



Das hat leider nicht den gewünschten Erfolg gebracht. In meinem richtigen Programm hatte ich das sogar schon so umgesetzt. Nur für das KKB war ich zu faul das mit aufzunehmen.




Marco13 hat gesagt.:


> Das setIcon müßte wohl auch mit SwingUtilities auf dem EDT gemacht werden, falls das nicht schon durch einen Buttonklick oder so ausgelöst wird. Ansonsten... beschreibe mal das "Flackern" genauer... die Kristallkugel in meinem Bauch sagt: Füg' mal in der main als erste Zeile
> System.setProperty("sun.awt.noerasebackground", "true");
> ein... aber die irrt sich auch manchmal



Schonmal über eine Kariere als professioneller Wahrsager nachgedacht  -  die richtigen Utensilien scheinst du ja schon zu haben 
Das System.set... funktioniert wie gewünscht, vielen Dank dafür.
Kannst du mir noch erklären, was der Befehl auslöst?


----------



## Marco13 (29. Mai 2012)

Sooo genau kann ich das auch nicht (und ich bin nicht sicher, ob es überhaupt jemand kann  ). Man findet im Netzt einiges dazu. Im wesentlichen gilt so diese "Faustregel": Wenn irgendwas mit OpenGL (also auch Java3D) immer mal so grau aufflackert (oder grau bleibt und erst bei einem Neuzeichnen was zu sehen ist) hilft meistens diese magische Zeile ....


----------

