I am writing a Java application that is supposed to scroll the waveform smoothly across the screen. I spent a lot of time on various tutorials to figure out how to make this animation as smooth as possible. As far as I can tell, I did all the normal things to eliminate flickering (drawing on the screen buffer and rendering in one step, plus overriding the update so that the screen is not blank), but my animation still flickers, and the screen looks like it was muffled before each update.
I'm sure there is something fundamental (and probably simple) that I miss, but I have no ideas. I will post below a class that illustrates the problem. Any help would be greatly appreciated.
import java.awt.*; import javax.swing.*; public class FlickerPanel extends JPanel implements Runnable { private float [] pixelMap = new float[0]; 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<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<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); } }
Simon andrews
source share