Foros del Web » Programación para mayores de 30 ;) » Java »

Cómo evitar el parpadeo de la imagen con Swing y Java 2D

Estas en el tema de Cómo evitar el parpadeo de la imagen con Swing y Java 2D en el foro de Java en Foros del Web. Necesito ayuda para arreglar mi juego. He hecho todo lo posible para activar el doble buffer y evitar parpadeos, pero no es suficiente. Las imágenes ...
  #1 (permalink)  
Antiguo 17/10/2015, 11:50
Avatar de andrespintonegreira  
Fecha de Ingreso: octubre-2015
Mensajes: 4
Antigüedad: 8 años, 6 meses
Puntos: 1
Cómo evitar el parpadeo de la imagen con Swing y Java 2D

Necesito ayuda para arreglar mi juego. He hecho todo lo posible para activar el doble buffer y evitar parpadeos, pero no es suficiente. Las imágenes estáticas quedan perfectas, sin embargo cuando algo se mueve en la pantalla empieza a parpadear como si se estuviera dibujando a la vez en dos posiciones distintas.

El parpadeo solo aparece en Linux, en Windows funciona bien. Necesito que funcione en Linux y ya no sé qué hacer. Os agradecería mucho que probarais el programa y me dierais alguna idea.

ESTA ES LA CLASE DE LA VENTANA

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class clsWindow extends JFrame implements WindowListener{
clsPanel panel;

public clsWindow(){
addWindowListener(this);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOS E);
panel = new clsPanel();
setContentPane(panel);
setTitle("Flickering example");
setResizable(false);
setSize(800, 600);
setVisible(true);
}

public void addNotify(){
super.addNotify();
setResizable(false);
Insets insets = getInsets();
setSize(
(int) Math.round(800 + insets.left + insets.right),
(int) Math.round(600 + insets.top + insets.bottom)
);
setLocationRelativeTo(null);
this.getContentPane().requestFocusInWindow();
}

public void windowOpened (WindowEvent e){}
public void windowActivated (WindowEvent e){this.getContentPane().requestFocusInWindow();}
public void windowDeactivated(WindowEvent e){}
public void windowIconified (WindowEvent e){}
public void windowDeiconified(WindowEvent e){this.getContentPane().requestFocusInWindow();}

public void windowClosing (WindowEvent e){
if(panel != null){panel.stopAnimation();} // Stop animation thread
dispose();
System.exit(0);
}

public void windowClosed (WindowEvent e){}

}

ESTA ES LA CLASE DEL PANEL

import java.awt.*;
import javax.swing.*;

public class clsPanel extends JPanel implements Runnable{
private int Xposition, increment;
private boolean direction;

private static final int TEMPORAL_RESOLUTION = 10; // milliseconds
// Frame duration. Chosen value must be multiple of temporal resolution.
// 40 ms 25 fps
// 35 ms 28,5 fps
// 30 ms 33,3 fps
// 25 ms 40 fps
// 20 ms 50 fps
// 15 ms 66,6 fps
private static final float FRAME_DURATION = 20; // ms

private Thread animationThread;
private volatile boolean running; // This variable is shared with the event dispatch thread

public clsPanel(){
this.setIgnoreRepaint(true);
increment = 2;
direction = true;
}

public void addNotify(){
super.addNotify();
setDoubleBuffered(true);
running = true;
animationThread = new Thread(this);
animationThread.start();
}

public void stopAnimation(){running = false;}

public void run() {
long loopDuration = 0, previous = 0, delay = 0, aux = 0, interim = 0, correction = 0;
int lastFrame = 0;

// Main loop
previous = 0;
while (running){
motion(); // move the square
if(lastFrame == FRAME_DURATION){lastFrame = 0; repaint();} // Repaint
aux = System.nanoTime();
if(previous == 0){
correction = 0;
loopDuration = (TEMPORAL_RESOLUTION * 1000000);
}else{
loopDuration = aux - previous;
correction = loopDuration - (TEMPORAL_RESOLUTION * 1000000);
}

previous = aux;
delay = correction;

do{
try {Thread.sleep(1);} catch (InterruptedException e) {};
interim = System.nanoTime() - aux;
delay = delay + interim;
aux = System.nanoTime();
} while(delay < (TEMPORAL_RESOLUTION - 1) * 1000000);

lastFrame += TEMPORAL_RESOLUTION;
}
}

private void motion(){
if(direction == true){
if(Xposition < 700){
Xposition += increment;
}else{
direction = false;
}
}else{
if(Xposition > 0){
Xposition -= increment;
}else{
direction = true;
}
}
}

public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;

g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASI NG, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIA LIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

// Background
g2d.setColor(Color.decode("0xe0e0e0"));
g2d.fillRect(0, 0, 800, 600);

// Square
g2d.setColor(Color.decode("0x202020"));
g2d.fillRect((int) Math.round(Xposition), 250, 100, 100);

g2d.dispose();
Toolkit.getDefaultToolkit().sync();
}

}

Última edición por andrespintonegreira; 17/10/2015 a las 17:25 Razón: Nueva información sobre el problema
  #2 (permalink)  
Antiguo 18/10/2015, 14:30
Avatar de loganbdn  
Fecha de Ingreso: enero-2009
Ubicación: Badalona
Mensajes: 114
Antigüedad: 15 años, 3 meses
Puntos: 1
Respuesta: Cómo evitar el parpadeo de la imagen con Swing y Java 2D

En Canvas para que no borre el fondo y haga parpadeo se añade también el método update() de esta manera:

public void update(Graphics g) {
paint(g);
}

Con JPanel quizás debe ser algo parecido...
  #3 (permalink)  
Antiguo 19/10/2015, 07:07
Avatar de andrespintonegreira  
Fecha de Ingreso: octubre-2015
Mensajes: 4
Antigüedad: 8 años, 6 meses
Puntos: 1
Respuesta: Cómo evitar el parpadeo de la imagen con Swing y Java 2D

Gracias por el consejo. Después de leer tu respuesta he consultado la documentación y he visto que JPanel no tiene método update() ni ninguno equivalente. De todas formas el programa funciona de maravilla en Windows. Parece que el parpadeo se debe a un problema de implementación en Linux. Aunque la mayoría de los usuarios de mi juego usan Windows no está bien dejar tirados al resto.

Ayer leí en otro foro algo sobre este problema de parpadeo en Linux, pero no daban la solución. Preguntaré en foros que estén más especializados en gráficos.

Etiquetas: clase, jframe, parpadeo, programa, swing
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 13:50.