DoubleBuffering im AWT - Flackern verhindern

Aus Byte-Welt Wiki
Version vom 24. März 2009, 01:20 Uhr von AndreUhres (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „Hast du schonmal eine Anwendung (bzw. Applet) mit einer Animation entwickelt? Damit nichts flackert und die Animation glatt abläuft, benötigen wir Doppelpufferu...“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springenZur Suche springen

Hast du schonmal eine Anwendung (bzw. Applet) mit einer Animation entwickelt? Damit nichts flackert und die Animation glatt abläuft, benötigen wir Doppelpufferung. Swing hat von Haus aus schon Doppelpufferung eingebaut. Falls wir aus irgendeinem Grund auf AWT zurückgreifen wollen, müssen wir die Doppelpufferung selbst programmieren. Hier ist ein kleines Beispiel (gem. Zizilamoroso). Es enthält die Klasse "PanelDoubleBuffered", welche die Doppelpufferung besorgt und die wir einfach nur erweitern müssen, wann immer wir Doppelpufferung in AWT benötigen: <code=java>/*

* AwtDoubleBuffered.java
*/

import java.applet.*; import java.awt.*;

public class AwtDoubleBuffered extends Applet implements Runnable {

   private AnimatedPanel graphic2;
   private boolean running;
   /** Initializes the applet AwtDoubleBuffered */
   @Override
   public void init() {
       try {
           EventQueue.invokeAndWait(new Runnable() {
               public void run() {
                   setLayout(new BorderLayout());
                   graphic2 = new AnimatedPanel();
                   add(graphic2);
               }
           });
       } catch (Exception ex) {
           ex.printStackTrace();
       }
   }
   @Override
   public void start() {
       new Thread(this).start();
   }
   public void run() {
       running = true;
       while (running) {
           graphic2.animateToTheRight();
           try {
               Thread.sleep(50);
           } catch (InterruptedException ex) {
               ex.printStackTrace();
           }
       }
   }
   @Override
   public void stop() {
       running = false;
   }

}

class PanelDoubleBuffered extends Panel {

   private int width;
   private int height;
   private Image offscreen;
   private Graphics graphics;
   public PanelDoubleBuffered() {
       super();
   }
   @Override
   public void update(final Graphics g) {
       paint(g);
   }
   @Override
   public void paint(final Graphics g) {
       super.paint(g);
       // checks the buffersize with the current panelsize
       // or initialises the image with the first paint
       if (width != getSize().width ||
               height != getSize().height ||
               offscreen == null || graphics == null) {
           resetBuffer();
       }
       if (graphics != null) {
           //this clears the offscreen image, not the onscreen one
           graphics.clearRect(0, 0, width, height);
           //calls the paintbuffer method with
           //the offscreen graphics as a param
           paintBuffer(graphics);
           //we finaly paint the offscreen image onto the onscreen image
           g.drawImage(offscreen, 0, 0, this);
       }
   }
   private void resetBuffer() {
       // always keep track of the image size
       width = getSize().width;
       height = getSize().height;
       // clean up the previous image
       if (graphics != null) {
           graphics.dispose();
       }
       if (offscreen != null) {
           offscreen.flush();
       }
       // create the new image with the size of the panel
       offscreen = createImage(width, height);
       graphics = offscreen.getGraphics();
   }
   public void paintBuffer(final Graphics g) {
       // in classes extended from this one, add something to paint here!
       // always remember, g is the offscreen graphics
   }

}

class AnimatedPanel extends PanelDoubleBuffered {

   private int posX;
   public AnimatedPanel() {
       super();
       posX = 0;
       setBackground(Color.BLACK);
   }
   public void animateToTheRight() {
       // this can be called from everywhere, anytime
       posX++;
       repaint();
   }
   // attention: we don't touch update() and paint() anymore
   // we use paintbuffer() instead
   @Override
   public void paintBuffer(final Graphics g) {
       // g is the offscreen graphics
       g.setColor(Color.WHITE);
       g.drawString("doublebuffered", posX, 20);
   }

}</code=java>