title: How to eliminate java animation flickering
body: <p>I'm writing a java application which needs to scroll a waveform smoothly over the screen. I've spend ages going through various tutorials to figure out how to make this animation as smooth as possible.  As far as I can see I've done all the normal things to eliminate flickering (drawing to offscreen buffer and rendering in a single step, plus overriding update so the screen isn't blanked), but my animation still flickers, and the screen looks like it's being blanked before each update.</p>
  
  <p>I'm sure there's something fundamental (and probably simple) I'm missing, but I'm out of ideas.  I'll post a class below which illustrates the problem.  Any help would be much appreciated.</p>
  
  <pre><code>import java.awt.*;
  import javax.swing.*;
  
  public class FlickerPanel extends JPanel implements Runnable {
  
      private float [] pixelMap = new float[0];
  
      /** Cached graphics objects so we can control our animation to reduce flicker **/
      private Image screenBuffer;
      private Graphics bufferGraphics;
  
      public FlickerPanel () {
          Thread t = new Thread(this);
          t.start();
      }
  
      private float addNoise () {
          return (float)((Math.random()*2)-1);
      }
  
      private synchronized void advance () {
          if (pixelMap == null || pixelMap.length == 0) return;
          float [] newPixelMap = new float[pixelMap.length];
          for (int i=1;i&lt;pixelMap.length;i++) {
              newPixelMap[i-1] = pixelMap[i];
          }
  
          newPixelMap[newPixelMap.length-1] = addNoise();     
  
          pixelMap = newPixelMap;
      }
  
      public void run() {
          while (true) {
              advance();
              repaint();
  
              try {
                  Thread.sleep(25);
              } catch (InterruptedException e) {}
  
          }
      }
  
      private int getY (float height) {
          double proportion = (1-height)/2;
          return (int)(getHeight()*proportion);
      }
  
      public void paint (Graphics g) {
  
          if (screenBuffer == null || screenBuffer.getWidth(this) != getWidth() || screenBuffer.getHeight(this) != getHeight()) {
              screenBuffer = createImage(getWidth(), getHeight());
              bufferGraphics = screenBuffer.getGraphics();
          }
  
          if (pixelMap == null || getWidth() != pixelMap.length) {
              pixelMap = new float[getWidth()];
          }
  
          bufferGraphics.setColor(Color.BLACK);
  
          bufferGraphics.fillRect(0, 0, getWidth(), getHeight());
  
          bufferGraphics.setColor(Color.GREEN);
  
          int lastX = 0;
          int lastY = getHeight()/2;
  
          for (int x=0;x&lt;pixelMap.length;x++) {
              int y = getY(pixelMap[x]);
              bufferGraphics.drawLine(lastX, lastY, x, y);
              lastX = x;
              lastY = y;
          }
  
          g.drawImage(screenBuffer, 0, 0, this);
      }
  
      public void update (Graphics g) {
          paint(g);
      }
  
      public static void main (String [] args) {
          JFrame frame = new JFrame("Flicker test");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setContentPane(new FlickerPanel());
          frame.setSize(500,300);
          frame.setVisible(true);
      }
  
  
  }
  </code></pre>