# Flackern beim neuzeichnen von JPanel



## Nicole81 (21. Jun 2007)

Hallöle,

ich habe ein Panel auf dem ein Label sitzt. In dieses Label lade ich 50 mal in der Sekunde ein Image.
Jetzt flackert das aber sehr stark. Kann man das irgendie verhindern?

Hier mal die Methode, welche das Bild setzt. Das ganze wird über einen Timer gesteuert:


```
Image i = s2mGUI.getGrid(s2mGUI.getCurrentGridWorkspace()).getGridImage();
				Image is = null;
				
				if (rbmiQLow.isSelected())
					is = i.getScaledInstance(getWidth()-20,getHeight()-70, Image.SCALE_FAST);
				if (rbmiQHigh.isSelected())
					is = i.getScaledInstance(getWidth()-20,getHeight()-70, Image.SCALE_SMOOTH);

				ImageIcon ii = new ImageIcon(is);
				
				lImage.setIcon(ii);
```

Danke euch!


----------



## The_S (21. Jun 2007)

Skaliere dein Image schon beim Starten des Programms auf alle Möglichen Größen/Arten und speichere dir das jeweils in z. B. einer Liste. Beim neuzeichnen greifst du dann einfach nur noch auf das bereits skalierte Image zu, anstatt das Ursprungsimage neu zu skalieren.


----------



## ice-breaker (21. Jun 2007)

Ein weiterer signifikanter Unterschied kann durch das Nutzen von Double-Buffering genutzt werden


----------



## The_S (21. Jun 2007)

Wüsste jetzt nicht, was das beim Zeichnen eines einzelnen Bildes an Vorteilen bringen soll ???:L


----------



## Nicole81 (21. Jun 2007)

ich dachte JPanel hat double Buffering bereits implementiert.
Ich führe ja keine einzelnen Zeichenoperationen durch, sondern kopiere das gesamte Bild ja in das Label.

@hobbit
das geht leider nicht, das sich das Originalbild auch im 20ms Takt ändert. Dieses soll dann verkleinert (so ne Art prewiew) in diesem Panel angezeigt werden


----------



## The_S (21. Jun 2007)

Hm, wenn alle 20 Millisekunden ein komplett neues Bild geladen, skaliert und dargestellt werden soll, ist ein gewisses flackern doch normal, schon allein dadurch, dass das Bild nicht fließend ins nächste übergeht erscheint es für das menschliche Auge "flackernt". Außerdem braucht das nunmal seine Zeit, wenn der Rechner zu schwach ist, haste da kaum eine Chance.

Wie viele unterschiedliche Bilder gibts denn zum laden/skalieren?


----------



## Nicole81 (21. Jun 2007)

bilder gibt es unendlich viele, da in dem bild eine animation eines zeichenprogramms dargestellt wird.

habe es gerade mit 10 bzw. 2 bildern pro sekunde getestet. da flackert es komischerweise auch.


----------



## Wildcard (21. Jun 2007)

Nicole81 hat gesagt.:
			
		

> Hallöle,
> 
> ich habe ein Panel auf dem ein Label sitzt. In dieses Label lade ich 50 mal in der Sekunde ein Image.
> Jetzt flackert das aber sehr stark. Kann man das irgendie verhindern?
> ...


Ich vermute einen javax.swing.Timer?
Das heißt du hast den kompletten Code im EDT.
Verlager das laden und eventuell auch das skalieren in einen anderen Thread.


----------



## masta // thomas (21. Jun 2007)

Ich hab den Swing Timer noch nie wirklich benutzt - bringt er irgendwelche Vorteile gegenüber einem Thread? Wann/warum ist der Einsatz des Timers sinnvoller als eines Threads?


----------



## Wildcard (21. Jun 2007)

masta // thomas hat gesagt.:
			
		

> Ich hab den Swing Timer noch nie wirklich benutzt - bringt er irgendwelche Vorteile gegenüber einem Thread? Wann/warum ist der Einsatz des Timers sinnvoller als eines Threads?


Du kannst schon lesen, oder?
Ich rate dazu *keinen* Timer zu verwenden, sondern einen Thread


----------



## Nicole81 (21. Jun 2007)

ich habe einen java.util.Timer benutzt.

ich bin anfänger, das ist mein erster timer-einsatz, wie mache ich das mit den extra threads?


----------



## masta // thomas (21. Jun 2007)

Meine Frage war unabhängig von dem Thema hier, lieber Wildcard  Oder rätst du grundsätzlich die Benutzung des Timers ab?


----------



## Wildcard (21. Jun 2007)

masta // thomas hat gesagt.:
			
		

> Meine Frage war unabhängig von dem Thema hier, lieber Wildcard  Oder rätst du grundsätzlich die Benutzung des Timers ab?


Warum stellst du sie dann hier?
Ein swing Timer hat den Vorteil das er leicht zu handhaben ist und das er im EDT ausgeführt wird.
Nachteilig ist, das er im EDT ausgeführt wird  :wink:  und das er nicht sehr genau ist.


----------



## Nicole81 (21. Jun 2007)

wildcard, wärest du so nett mir noch einen tip zu geben, wie ich das mit den extra threads mache?


----------



## Wildcard (21. Jun 2007)

Ich weiß nicht mit was du genau Probleme hast, also lies am besten das Thread Kapitel in der Javainsel.


----------



## masta // thomas (21. Jun 2007)

Danke für die Erklärung, Wildcard


----------



## The_S (22. Jun 2007)

Nicole81 hat gesagt.:
			
		

> wildcard, wärest du so nett mir noch einen tip zu geben, wie ich das mit den extra threads mache?



zum Einen hat Wildcard recht, zum Anderen könnte es z. B. so aussehen


```
new Thread(new Runnable() {
   public void run() {
      while (true) {
          loadPic();
          scalePic();
          setPic();
          try {
              Thread.sleep(20);
          }
          catch (InterruptedException e){
               e.printStackTrace();
          }
      }
   }
}).start();
```


----------



## Nicole81 (22. Jun 2007)

Danke Hobbit, ich hab das gestern mal so ähnlich hinbekommen, leider zieht das Bild trotzdem noch schlieren :  
Auch bei 2-10 Bildern pro Sekunde. Das kann doch irgendwie nicht sein, es laufen doch aufwendige 3D-Spiele mit 60 Bildern pro Sekunde, da darf doch so eine verhältnismässig einfache Operation nicht flackern.



```
public class S2M_GUI_Run_Thread extends Thread
	{
		private S2M_GUI_Run s2mRun;
		
		public S2M_GUI_Run_Thread(S2M_GUI_Run gr)
		{
			s2mRun = gr;
		}
				
		public void run() 
		{
			s2mRun.setImage();	
			try {t.sleep(refreshtime);} 
			catch (InterruptedException e) {e.printStackTrace();}
			run();
		}
	}



// in S2M_GUI_Run Klasse
	public void setImage()
	{
		if (this.isVisible())
		{
			try
			{
				Image i = s2mGUI.getGrid(s2mGUI.getCurrentGridWorkspace()).getGridImage();
				Image is = null;
				
				if (rbmiQLow.isSelected())
					is = i.getScaledInstance(getWidth()-20,getHeight()-95, Image.SCALE_FAST);
				if (rbmiQHigh.isSelected())
					is = i.getScaledInstance(getWidth()-20,getHeight()-95, Image.SCALE_SMOOTH);

				ImageIcon ii = new ImageIcon(is);
				
				lImage.setIcon(ii);
			}
			catch (Exception e)
			{
				
			}
		}
	}
```


----------



## The_S (22. Jun 2007)

Naja, bei 3D-Spielen sind alle Texturen schon geladen, also im Speicher. Außerdem müssen die Grafiken nicht mehr skalliert werden. Du hast hier einen Zugriff auf das File-System, musst ein Bild auslesen/parsen und dieses dann nochmal skalieren, und das einige male pro sekunde.

Was noch etwas bringen könnte, wären zwei mehr oder minder synchronisierte Threads. Der eine Thread aktualisiert immer die Anzeige, wartet 20ms und aktualisiert dann wieder die Anzeige. Bevor der erste Thread dann schläft, teilt er dem 2. Thread mit, dass er das nächste Bild laden und skalieren soll.

Könnte aber auch sein, dass diese Vorgehensweiße nur noch das Flackern verschlimmert, aber einen Versuch ist es wert  .


----------



## Nicole81 (22. Jun 2007)

Zugriff auf das file system hab ich nicht, das originalbild ist ebenfalls schon im speicher.

Ich versuche das mal mit den 2 Threads, danke!


----------

