Doppelpufferung mit Canvas

Java’s hauseigene Canvas verfügen über keine Doppelpufferung was unschönes Flackern hervorrufen kann. Deshalb müssen wir uns dies selbst nachbauen. Die Klasse, die uns hier behilflich sein können nennen sich BufferStrategy und VolatileImage. VolatileImages sind Hardware-beschleunigt, weshalb uns dies einen Performance-Schub bringen kann.

Es ist zu beachten, dass unsere Zeichenfläche anweisen keine repaint()-Befehle mehr entgegen nehmen soll, da wir dies ja selbst machen wollen (Z. 35). Außerdem weist uns die Doku des VolatileImages darauf hin, dass dessen Inhalt „verloren“ gehen kann. Wir müssen also bei jedem Zeichenvorgang überprüfen ob dies der Fall war um dann ein neues VolatileImage erstellen zu können. Als letztes müssen wir noch beachten, dass wir bei jedem Neuzeichnen das vorherige angezeigte Image löschen (Z. 63) und das neu gerenderte auch anzeigen (Z. 70).

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;
import java.awt.image.VolatileImage;

import javax.swing.JFrame;

public class CanvasTest implements Runnable {

	private Canvas c = null;
	private GraphicsEnvironment ge = null;
	private GraphicsConfiguration gc = null;
	private VolatileImage backBuffer = null;
	private BufferStrategy strategy = null;

	private int x = 0;

	public static void main(String[] args) {
		new CanvasTest();
	}

	public CanvasTest() {
		c = new Canvas();
		c.setPreferredSize(new Dimension(200, 200));

		JFrame f = new JFrame("CanvasTest");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setSize(new Dimension(200, 200));
		f.setLocation(100, 100);
		f.add(c);
		f.setIgnoreRepaint(true);
		f.setVisible(true);

		createBackBuffer();
		c.createBufferStrategy(2);
		strategy = c.getBufferStrategy();
		new Thread(this).start();
	}

	@Override
	public void run() {
		while (true) {
			x += 1;
			renderBackBuffer();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void renderBackBuffer() {
		if (backBuffer == null || backBuffer.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
			createBackBuffer();
		}

		Graphics g1 = backBuffer.getGraphics();
		g1.clearRect(0, 0, c.getWidth(), c.getHeight());
		render(g1);
		g1.dispose();

		Graphics g2 = strategy.getDrawGraphics();
		g2.drawImage(backBuffer, 0, 0, c);
		g2.dispose();
		strategy.show();
	}

	private void createBackBuffer() {
		ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
		backBuffer = gc.createCompatibleVolatileImage(c.getWidth(), c.getHeight());
	}

	private void render(Graphics gr) {
		Graphics g = backBuffer.getGraphics();
		g.setColor(Color.BLACK);
		g.drawString("" + x, 50, 50);
		g.dispose();
	}
}
Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: