Utilizando Doble Buffer en JFrame mediante BufferStrategy

27Feb08

Muchas veces queremos dibujar (gráficos, mapas, imagenes, etc) sobre un JFrame (generalmente reimplementando
paint(Graphics g)) y si estos son dinámicos podemos llegar a notar que el Frame parpadeá.

Ante esta situación notamos que necesitamos utilizar una técnica de Doble Buffering de forma de evitar estos inconvenientes, y poder realizar y obtener los mismo resultados que con un JPanel (que ya tiene implementado y activado el doble buffer por defecto).

Para ello utilizamos la clase java.awt.image.BufferStrategy.

Por ejemplo si tenemos implementado algo como:

...
import java.awt.Graphics2D;
...

public class SinDBufferJFrame extends javax.swing.JFrame
    ...

    public SinDBufferJFrame () {
        ...
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = null;

        try {
            g2 = g.create();

            paint(g2);
        } finally {
            g2.dispose();
        }
    }

    public void paint(Graphics2D g2) {
        ...
        //Acá dibujamos lo que queremos mostrar
        ...
    }

    ...
}

podemos modificar rápidamente nuestro JFrame para utilizar Doble Buffer de la siguiente forma:

...
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
...

public class DBufferJFrame extends javax.swing.JFrame

    ...
    private final BufferStrategy bf;
    ...

    public DBufferJFrame () {
        ...

        createBufferStrategy(2);        //creamos dos buffers
        bf = this.getBufferStrategy();  //obtenemos la estrategia del JFrame
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = null;

        try {
            //obtenemos uno de los buffers para dibujar
            g2 = (Graphics2D) bf.getDrawGraphics();

            paint(g2);
        } finally {
            g2.dispose();
        }

        //pintamos el buffer en pantalla
        bf.show();
    }

    public void paint(Graphics2D g2) {
        ...
        //Acá dibujamos lo que queremos mostrar
        ...
    }

    ...
}

Espero les sirva.
Saludos.

Más Info



3 Responses to “Utilizando Doble Buffer en JFrame mediante BufferStrategy”

  1. 1 ranatrix

    I found another example of this technique here:

    http://mobile-programming-and-games.blogspot.com/

    It’s great example with source code!

  2. run:
    Exception in thread “main” java.lang.IllegalStateException: Component must have a valid peer
    at java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:3756)
    at java.awt.Component$FlipBufferStrategy.(Component.java:3730)
    at java.awt.Component$FlipSubRegionBufferStrategy.(Component.java:4253)
    at java.awt.Component.createBufferStrategy(Component.java:3612)
    at java.awt.Window.createBufferStrategy(Window.java:3012)
    at java.awt.Component.createBufferStrategy(Component.java:3536)
    at java.awt.Window.createBufferStrategy(Window.java:2987)
    at cuadros.Ventana.(Main.java:56)
    at cuadros.Main.main(Main.java:303)
    Java Result: 1

  3. 3 Victor

    Exception in thread “AWT-EventQueue-0” java.lang.IllegalStateException: Component must have a valid peer
    at java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:3575)
    at java.awt.Component$FlipBufferStrategy.(Component.java:3549)
    at java.awt.Component$FlipSubRegionBufferStrategy.(Component.java:4031)
    at java.awt.Component.createBufferStrategy(Component.java:3450)
    at java.awt.Window.createBufferStrategy(Window.java:2957)
    at java.awt.Component.createBufferStrategy(Component.java:3379)
    at java.awt.Window.createBufferStrategy(Window.java:2932)
    at graficaskframe.graficador.(graficador.java:21)
    at graficaskframe.graficador$1.run(graficador.java:82)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)



A %d blogueros les gusta esto: