N'Abend zusammen !
Ich bin gerade dabei mir eine kleine Utility Klasse zu schreiben die ein animiertes JComponent liefert. Also im Grunde genommen so etwas wie eine GameLoop, nur eben das Sie nicht die Kontrolle über die gesamte GUI übernimmt sondern nur über eine einzelne Komponente.
Ich habe bisher nur kleinere Swing Anwendungen geschrieben die komplett ohne Threads auskamen (vom EDT mal abgesehen), somit bin ich ein absoluter Newbie beim Thema Threads.
Das Problem habe ich lokalisiert, während der Aufruf requester.update() immer schön wie erwartet abgearbeitet und auf seine Erledigung gewartet wird, wird der folgende Methodenaufruf canvas.repaint() nicht bzw. zeitversetzt abgearbeitet. Ich vermute mal das liegt daran das die update() Methode im aktuellen Thread erledigt wird, repaint() aber an den EDT weitergeleitet und dort irgendwann abgearbeitet wird, oder ?
Trotz mehrstündiger Suche hier im Forum und über Google find ich einfach keine Lösung ... wäre super wenn jemand hier nen Schraubenzieher zur Hand hätte um mir das Brett vorm Kopf abzuschrauben und mir erklärt wie ich die AnimationLoop auf die Beendigung der repaint Methode warten lassen kann ... ^^ Daaanke !!!!
Folgender Code (stark komprimiert um das Problem zu fokussieren):
Class AnimationLoop
Class AnimationLoopCanvas
Interface Animationable
Das ganze wird wie folgt eingebunden ...
Das Panel ist Teil eines Frames welches über
erzeugt wird.
Das Programm erzeugt folgende Ausgabe im Terminal:
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Methode draw aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
...
update() wird also mehrfach durchlaufen wird bis sich draw() (wird von repaint aufgerufen) mal bequemt etwas zu tun. Auch im späteren Verlauf wird draw() nicht wirklich konstant durchlaufen ...
Genauso beinflusst auch nur das Thread.Sleep(5) in der update Methode die Laufzeit der AnimationLoop, das Thread.Sleep(10) in der draw() Methode lässt die AnimationLoop kalt ...
Ich bin gerade dabei mir eine kleine Utility Klasse zu schreiben die ein animiertes JComponent liefert. Also im Grunde genommen so etwas wie eine GameLoop, nur eben das Sie nicht die Kontrolle über die gesamte GUI übernimmt sondern nur über eine einzelne Komponente.
Ich habe bisher nur kleinere Swing Anwendungen geschrieben die komplett ohne Threads auskamen (vom EDT mal abgesehen), somit bin ich ein absoluter Newbie beim Thema Threads.
Das Problem habe ich lokalisiert, während der Aufruf requester.update() immer schön wie erwartet abgearbeitet und auf seine Erledigung gewartet wird, wird der folgende Methodenaufruf canvas.repaint() nicht bzw. zeitversetzt abgearbeitet. Ich vermute mal das liegt daran das die update() Methode im aktuellen Thread erledigt wird, repaint() aber an den EDT weitergeleitet und dort irgendwann abgearbeitet wird, oder ?
Trotz mehrstündiger Suche hier im Forum und über Google find ich einfach keine Lösung ... wäre super wenn jemand hier nen Schraubenzieher zur Hand hätte um mir das Brett vorm Kopf abzuschrauben und mir erklärt wie ich die AnimationLoop auf die Beendigung der repaint Methode warten lassen kann ... ^^ Daaanke !!!!
Folgender Code (stark komprimiert um das Problem zu fokussieren):
Class AnimationLoop
Java:
package de.javosoft.java.utilitycollection.animationloop;
public final class AnimationLoop {
private AnimationLoopCanvas canvas;
private Animationable requester;
private boolean running = true;
public AnimationLoop(Animationable requester){
this.requester = requester;
canvas = new AnimationLoopCanvas(requester);
}
public AnimationLoopCanvas getCanvas(){
return canvas;
}
public void start() {
Thread loop = new Thread() {
@Override
public void run() {
loopAction();
}
};
loop.start();
}
private void loopAction(){
long beginTime, timeTaken, timeLeft;
while (true) {
beginTime = System.nanoTime();
requester.update();
canvas.repaint();
timeTaken = System.nanoTime() - beginTime;
timeLeft = (1000000000L / 50 - timeTaken) / 1000000L;
System.out.println("Verbrauchte Zeit: "+timeTaken/1000000L+" Wartezeit: "+timeLeft);
if (timeLeft < 10) timeLeft = 10;
try {
Thread.sleep(timeLeft);
} catch (InterruptedException ex) { }
}
}
}
Class AnimationLoopCanvas
Java:
package de.javosoft.java.utilitycollection.animationloop;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
public class AnimationLoopCanvas extends JComponent{
private Animationable requester;
public AnimationLoopCanvas(Animationable requester){
super();
this.requester = requester;
}
@Override
protected void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
requester.draw(g2d);
}
}
Interface Animationable
Java:
package de.javosoft.java.utilitycollection.animationloop;
import java.awt.Graphics2D;
public interface Animationable {
public void update();
public void draw(Graphics2D g);
}
Das ganze wird wie folgt eingebunden ...
Java:
package de.javosoft.java.utilitycollection.animationloop;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class PanelTest extends JPanel implements Animationable {
private AnimationLoop loop;
public PanelTest(){
this.setPreferredSize(new Dimension(800,600));
this.setLayout(null);
startTest();
}
private void startTest(){
loop = new AnimationLoop(this);
this.add(loop.getCanvas());
loop.getCanvas().setBounds(0,0,800,600);
loop.start();
}
@Override
public void update() {
System.out.println("Methode update aufgerufen");
//updates simulieren...
try {
Thread.sleep(5);
} catch (InterruptedException ex) {
Logger.getLogger(PanelTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void draw(Graphics2D g) {
System.out.println("Methode draw aufgerufen");
//Zeichnungen simulieren...
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(PanelTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Das Panel ist Teil eines Frames welches über
Java:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
FrameTest frame = new FrameTest();
}
});
Das Programm erzeugt folgende Ausgabe im Terminal:
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Methode draw aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
Methode draw aufgerufen
Methode update aufgerufen
Verbrauchte Zeit: 5 Wartezeit: 14
...
update() wird also mehrfach durchlaufen wird bis sich draw() (wird von repaint aufgerufen) mal bequemt etwas zu tun. Auch im späteren Verlauf wird draw() nicht wirklich konstant durchlaufen ...
Genauso beinflusst auch nur das Thread.Sleep(5) in der update Methode die Laufzeit der AnimationLoop, das Thread.Sleep(10) in der draw() Methode lässt die AnimationLoop kalt ...
Zuletzt bearbeitet: