Search code examples
javagraphicsjappletdoublebuffered

I can't get double buffering to work


I have tried quite a few tutorials and I can't seem to get double buffering to work. Here is my main (the update() method is the code i tried, but I still see flickering):

public class Main extends JApplet implements Runnable {
    private static final long serialVersionUID = 1L;
    private static int width = 900;
    private static int height = 600;
    public static int fps = 60;
    public Thread thread = new Thread(this);
    private Image dbImage;
    private Graphics dbg;
    public static Ailoid ailoid = new Ailoid();

    // Initialize
    public void init() {
        setSize(width, height);
        setBackground(Color.white);

        ailoid.setLocation(new Location(100, 100));
        AlienManager.registerAlien(ailoid);
    }

    // Paint graphics
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.green);
        for (Alien alien : AlienManager.getAliens()) {
            Location loc = alien.getLocation();
            int x = loc.getX();
            int y = loc.getY();
            g.fillRect(x, y, 10, 20);
        }
    }

    // Update graphics for double buffering
    public void update(Graphics g) {
        if (dbImage == null) {
          dbImage = createImage (width, height);
          dbg = dbImage.getGraphics();
        }

        dbg.setColor (getBackground ());
        dbg.fillRect (0, 0, width, height);

        dbg.setColor (getForeground());
        paint (dbg);

        g.drawImage (dbImage, 0, 0, this);
    }

    // Thread start
    @Override
    public void start() {
        thread.start();
    }
    // Thread stop
    @Override
    public void destroy() {
        thread = null;
    }

    // Thread run
    @Override
    public void run() {
        while (thread != null) {
            Updater.run();
            repaint();
            try {
                // 1000 divided by fps to get frames per millisecond
                Thread.sleep(1000 / fps);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

If someone could help it would be greatly appreciated!


Solution

  • Instead of drawing your objects one by one, draw them on an image and then tell the renderer to draw that entire image. This eliminates the flickering.

    Here's an example of how you might accomplish it.

    class DoubleBufferedCanvas extends Canvas {
    
        public void update(Graphics g) {
        Graphics offgc;
        Image offscreen = null;
        Dimension d = size();
    
        // create the offscreen buffer and associated Graphics
        offscreen = createImage(d.width, d.height);
        offgc = offscreen.getGraphics();
        // clear the exposed area
        offgc.setColor(getBackground());
        offgc.fillRect(0, 0, d.width, d.height);
        offgc.setColor(getForeground());
        // do normal redraw
        paint(offgc);
        // transfer offscreen to window
        g.drawImage(offscreen, 0, 0, this);
        }
    }