*Markus: Thread fängt immer "von vorne" an?

Beitrag lesen

Hallo,

Stattdessen könntest du einen Backbuffer verwenden, indem du z.B. ein
BufferedImage erzeugt und nur in diese zeichnest. Sobald du mit dem
Zeichen fertig bist, gibst du das BufferedImage über g.drawImage(...)
auf den Panel aus. [...]

Du hast recht. Auf diese Weise funktioniert es.

Lass mal diese Zeile weg:
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Stattdessen rufst du dann z.B. "System.exit(0)" in PaintPanel.run()
als letzte Anweisung auf. Dann dürfte noch alles, was nach der
while-Schleife kommt, ausgeführt werden.

Auch hier hast du recht.

Übrigens, der Aufruf "Thread.yield()" dürfte an dieser Stelle reichlich
sinnlos sein, weil du den Thread ohnehin schlafen legst und somit
andere Threads ausgeführt werden können.

Ok, ich wusste nicht genau, was der Thread im Schlafzustand macht und ob er es deswegen zulässt, andere Threads aufzurufen.
Hier nun meine Lösung:

  
import java.awt.Color;  
import java.awt.Graphics;  
import java.awt.Image;  
import java.awt.LayoutManager;  
import java.awt.Toolkit;  
import javax.swing.JPanel;  
  
public class PaintPanel extends JPanel implements Runnable {  
 private final int DOTSIZE = 10;  
 private Image image = null;  
 private Graphics g;  
  private int screenWidth;  
   private int screenHeight;  
 private boolean running = false;  
 private Thread animator;  
 private boolean isPaused = false;  
  
 public PaintPanel(LayoutManager manager)   {  
  setLayout(manager);  
     screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;  
    screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;  
 }  
  
 public void run() {  
  running = true;  
  while(running)   {  
   if (!isPaused)   {  
      bufferScreen();  
      paintScreen();  
   }  
   try {  
    Thread.sleep(1000);  
   } catch (InterruptedException e) {  
      e.printStackTrace();  
   }  
  }  
  System.out.println("Animation successfully stopped");  
  System.exit(0);  
 }  
  
 public void addNotify()   {  
//   only start the animation once the JPanel has been added to the JFrame  
  super.addNotify();  
  startAnimator();  
 }  
  
 public void startAnimator()   {  
  if (animator == null || !running)  {  
      animator = new Thread(this);  
   animator.start();  
  }  
 }  
  
 public void stopAnimator()   {  
  running = false;  
 }  
  
 public void pauseAnimator()   {  
  isPaused = true;  
 }  
  
 public void unpauseAnimator()   {  
  isPaused = false;  
 }  
 //Grafik muss zuerst gepuffert werden, damit beim Verschieben des Fensters  
 //diese nicht wieder verschwindet.  
 public void bufferScreen()   {  
     int xPosition = (int)(Math.random() * screenWidth);  
       int yPosition = (int)(Math.random() * screenHeight);  
  
       if (image == null)   {  
        image = createImage(screenWidth, screenHeight);  
        if (image == null)  
         return;  
        else  
         g = image.getGraphics();  
       }  
        g.setColor(Color.BLACK);  
        g.drawOval(xPosition, yPosition, DOTSIZE, DOTSIZE);  
        g.fillOval(xPosition, yPosition, DOTSIZE, DOTSIZE);  
 }  
  
    public void paintScreen()   {  
  
         Graphics graphic;  
         try {  
           graphic = this.getGraphics();  
           if ((graphic != null) && (image != null))  
             graphic.drawImage(image, 0, 0, null);  
           // Sync the display on some systems.  
           // (on Linux, this fixes event queue problems)  
           Toolkit.getDefaultToolkit().sync();  
           graphic.dispose();  
         }  
         catch (Exception e)   // quite commonly seen at applet destruction  
         { System.out.println("Graphics error: " + e);  }  
     } // end of paintScreen()  
}  

Und danke für die rasche Lösung. Jetzt ist mir auch klar, warum in der Game-Engine dies mit zwei Methoden gelöst wurde, eben wegen den Doppelbuffer-Effekt.

Markus