Estoy escribiendo una aplicación java que necesita desplazar una forma de onda suavemente sobre la pantalla. Pasé varias eras pasando por varios tutoriales para descubrir cómo hacer que esta animación sea lo más fluida posible. Por lo que puedo ver, he hecho todas las cosas normales para eliminar el parpadeo (dibujar en el búfer y renderizado fuera de pantalla en un solo paso, además de anular la actualización para que la pantalla no esté en blanco), pero mi animación aún parpadea, y la pantalla parece que está siendo borrado antes de cada actualización.Cómo eliminar el parpadeo de animación java
Estoy seguro de que hay algo fundamental (y probablemente simple) que me falta, pero me he quedado sin ideas. Publicaré una clase debajo que ilustra el problema. Cualquier ayuda sería muy apreciada.
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<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);
}
}
No puedo encontrar ningún problema con su código. Se ve bastante suave en mi escritorio. PD. Puede hacer esto mucho más eficientemente al tener solo un pixelMap y usarlo como un búfer cíclico, y proteger el acceso a él con un bloque sincronizado. Tal como está creando una nueva estructura, cada actualización debería estar bien. – Adam
+1 para [sscce] (http://sscce.org/). Brilla muy mal en mi plataforma. – trashgod
Después de haber jugado un poco más, parece que parte del problema puede deberse a que la estructura de datos de pixelMap se modificó durante el curso de una pintura, por lo que estoy rompiendo entre diferentes partes de la pantalla. Hacer un clon() de pixelMap al comienzo del método de pintura parece mejorar las cosas, pero el parpadeo todavía está allí, así que no creo que esta sea la respuesta completa. –