Swing Timer läuft unter Windows korrekt nicht aber unter UBUNTU

Blender3D

Top Contributor
Ich verwende einen SwingTimer, um eine Grafik zu animieren. Das funktioniert unter Windows xp - 10 super flüssig, aber unter UBUNTU beginnt die Animation nach ein paar Durchläufen, zu ruckeln.
Wer kann mir da weiterhelfen. Ich bin für jeden Input dankbar.
 

Blender3D

Top Contributor
Habe das Problem gelöst. Da das notwendige Wissen im Forum nicht vorhandenen war. Poste ich die Lösung für diejenigen die auf ein ähnliches Problem stoßen.
Das Problem liegt daran, dass unter Ubuntu Open Gl nicht automatisch aktiviert ist. Da ich Grafiken ausgebe kommt es bei der Ausgabe dieser Grafiken mangels aktiviertem Open GL zu Verzögerungen.
Daher kann nicht jeder Frame wiedergegeben werden und es ruckelt.
Workaround Java kann mittels einem Schalter Open Gl aktivieren.
java -Dsun.java2d.opengl=true -jar meinProgramm.jar
Und bei mir läuft jetzt alles wie unter Windows flüssig. Ich hatte ein ähnliches Problem mit meinem Pacman Clone unter Ubuntu. --> lies sich dadurch auch lösen.

:) Auf meiner Suche fand ich in anderen Foren das Problem mit dem Java Timer, wurde nirgendwo wirklich gelöst.
 

dzim

Top Contributor
Nur so aus Neugier: Hast du es mal mit einem ScheduledExecutorService oder einem Timer (also GUI-Unabhängig) versucht? Vielleicht ist das Problem einfach, das der Timer vom AWT/Swing-EventThread ausgelöst werden muss. Kenne mich da auch nicht genauer aus, aber habe bisher mich eher auf diese Klassen verlassen...
 

Blender3D

Top Contributor
Der Swing Timer funktioniert einwandfrei. Ich dachte ursprünglich, dass das Problem am Timer liegt.
Da unter Windows die Software einwandfrei lief und unter Ubuntu das Ruckeln auftrat, vermutet ich das das Problem an der Event Queue liegt und der Timer schuld hat. Ich versuchte es unter Linux mit der schnellsten Prozesspriorität und vielen anderen Dingen ohne Erfol. Durch einen Zufall stieß ich auf die obige Lösung.
Unter Swing ist die richtige Verwendung des Timer wichtig um gute Ergebnisse zu erhalten.
1) Zeichenoperationen immer mittels paintComponent() und niemals mit paint() ausführen
weil Swing beim Zeichnen eine Menge Dinge erledigt und paint irgendwo dazwischen aufgerufen wird.
Der Swing Timer ruft die Methode ActionListener auf und das passiert am Ende der Zeichenoperationen.
Wenn man sich daran hält läuft er sehr exakt. Ich verwende eine kleine Klasse um Grafiken animiert darzustellen. Die sehr gut arbeitet. Das Problem war unter Ubuntu das Open GL deaktiviert ist. Da das Zeichnen der Grafiken zu lange dauerte, wurde das nächste Timer Event ausgelöst und die nächste Zeichen Operation sollte ausgeführt werden bevor die vorige fertig war. So entstand das Flackern.
Aber durch das Aktivieren von Open GL funktioniert es jetzt sehr gut.
;)
 

thecain

Top Contributor
https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html hat gesagt.:
Note that the Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly. If the task might take a while to execute, then consider using a SwingWorker instead of or in addition to the timer. See Concurrency in Swing for instructions about using the SwingWorker class and information on using Swing components in multi-threaded programs.
Heisst: Du hast das eigentlich Problem nicht gelöst, sondern es lediglich "umgangen" da du nun mit OpenGl wieder schnell genug bist. Auf einem langsameren PC oder Notebook oder wenn mehr Arbeit vorhanden ist, wirst du wieder in das selbe Problem laufen.
 

dzim

Top Contributor
Mensch. Da hab ich ja gar nicht mal so falsch gelegen. Also wenn man so etwas wie Timer (ohne Swing) verwenden wurde, müsste man also SwinfUtils#invokeLater verwenden. Oder den Swing Wiener, der das für einen erledigt...
 

Blender3D

Top Contributor
Heisst: Du hast das eigentlich Problem nicht gelöst, sondern es lediglich "umgangen" da du nun mit OpenGl wieder schnell genug bist. Auf einem langsameren PC oder Notebook oder wenn mehr Arbeit vorhanden ist, wirst du wieder in das selbe Problem laufen.
Das ist eine Frage der Perspektive. Es bedeutet das auf meinem Netbook mit Atom Prozessor die Anwendung jetzt mit aktiviertem Open GL auch unter UBUNTU super läuft. Also aus meiner Sicht ist das Problem gelöst. Würde ich eine grafisches anspruchsvolle Spiel programmieren, würde ich auch hier Ansprüche an das System stellen. Oder auf C oder C++ ausweichen. Aber auch in diesen Fall müsste ich wohl auf Direkt X Open Gl oder ähnliches zurückgreifen müssen.
Und die Frage war ja: Warum läuft die Anwendung (gleicher Code) unter Windows super und unter UBUNTU nicht.
Antwort: Java hat unter Windows Open GL bei Default aktiviert und UBUNTU nicht.
 

dzim

Top Contributor
Ich finde zwar immer noch, du umgehst das Problem nur, statt es zu lösen, aber wenn dir diese IMHO unsaubere Methode genügt, dann ist das halt so.
 

Blender3D

Top Contributor
Note that the Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly. If the task might take a while to execute, then consider using a SwingWorker instead of or in addition to the timer. See Concurrency in Swing for instructions about using the SwingWorker class and information on using Swing components in multi-threaded programs.
Bei einer grafischen Anwendung ist der SwingWorker nicht angebracht. Oder soll ich einen SwingWorker beauftragen im Hintergrund Grafiken zeichnen zu lassen wenn die Hardware nicht mitkommt.
Die Grafik wir mangels Leistung der Hardware trotzdem flackern.
Der Timer macht genau das was er soll. Er ruft den Actionlistener im vereinbarten Zeitinterwall auf.
 

dzim

Top Contributor
ABER AUF DEM UI-THREAD! Sorry, bin wohl an der Shift-Taste festgehangen.

Was du willst: Ein garantiertes zeitgesteuertes Event. Das NICHT deine GUI beeinflusst.
Was du tust: Operationen auf dem GUI-Thread auslösen, die - wenn sie zu lange brauchen - die GUI zum stottern bringen.

Nur weil du den negativen Einfluss des SwingTimers nicht mehr siehst, heisst es nicht, dass er nicht mehr da ist. Das ist eine Vogel-Strauss-Taktik.

Nutz einfach einen anderen Timer, der die Arbeit *wirklich* auf einem anderen Thread tut und - wenn notwendig - über SwingUtils#invokeLater - die GUI updated.
Und á la Trumpel: Period.
 

Blender3D

Top Contributor
Danke für Deine Hinweise. Aber ich denke Du hast mein Problem nicht wirklich verstanden.
Wenn ich einen anderen Timer nutze, der dafür Sorge trägt, dass die Animation flüssig läuft stehe ich bei deaktiviertem Open GL wieder vor dem selben Problem. Der Timer versucht alle 20 ms die Grafik zeichnen zu lassen. Der Zeichenvorgang dauert, trotz anderem Timer zu lang, weil die Grafikausgabe zu langsam ist. Jetzt versucht, der andere Timer das nächste Bild zu zeichnen ... es kommt zu keiner flüssigen Animation.
Ich verwende SwingWorker für Aufgaben, die nicht im Millisekundenbereich liegen. Z.B. verwende ich diesen, wenn ich im Hintergrund zip files entpacken muss, oder für Kopieroperationen. dafür ist er laut Java auch vorgesehen.
Worker Threads and SwingWorker
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.
 

Ähnliche Java Themen

Neue Themen


Oben