DoubleBuffering im AWT - Flackern verhindern: Unterschied zwischen den Versionen
Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springenK |
K |
||
(2 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 3: | Zeile 3: | ||
[[Datei:doublebuffering.jpg]] | [[Datei:doublebuffering.jpg]] | ||
− | < | + | <syntaxhighlight lang="java"> |
/* | /* | ||
* AwtDoubleBuffered.java | * AwtDoubleBuffered.java | ||
Zeile 170: | Zeile 170: | ||
} | } | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
− | [[Kategorie:Java]] | + | [[Kategorie:Java 2D]] |
+ | [[Kategorie:AWT]] | ||
[[Kategorie:Tutorials (Java)]] | [[Kategorie:Tutorials (Java)]] | ||
[[Kategorie:Java-Codeschnipsel]] | [[Kategorie:Java-Codeschnipsel]] |
Aktuelle Version vom 22. Dezember 2018, 10:19 Uhr
Hast du schonmal eine Anwendung (bzw. Applet) mit einer Animation entwickelt? Damit nichts flackert und die Animation glatt abläuft, benötigen wir Doppelpufferung. Swing hat von Haus aus schon Doppelpufferung eingebaut. Falls wir aus irgendeinem Grund auf AWT zurückgreifen wollen, müssen wir die Doppelpufferung selbst programmieren. Hier ist ein kleines Beispiel (nach Zizilamoroso). Es enthält die Klasse "PanelDoubleBuffered", welche die Doppelpufferung besorgt und die wir einfach nur erweitern müssen, wann immer wir Doppelpufferung in AWT benötigen:
/*
* AwtDoubleBuffered.java
*/
import java.applet.*;
import java.awt.*;
import java.lang.reflect.*;
import java.util.logging.*;
public class AwtDoubleBuffered extends Applet implements Runnable {
private AnimatedPanel animatedPanel;
private boolean running;
/** Initializes the applet AwtDoubleBuffered */
@Override
public void init() {
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
setLayout(new BorderLayout());
animatedPanel = new AnimatedPanel();
add(animatedPanel);
}
});
} catch (final InterruptedException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
} catch (final InvocationTargetException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void start() {
new Thread(this).start();
}
@Override
public void stop() {
setRunning(false);
}
public void run() {
setRunning(true);
while (isRunning()) {
animatedPanel.animateToTheRight();
waitMilliseconds(50);
}
}
private void waitMilliseconds(final int millis) {
try {
Thread.sleep(millis);
} catch (final InterruptedException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
public boolean isRunning() {
return running;
}
public void setRunning(final boolean running) {
this.running = running;
}
}
class PanelDoubleBuffered extends Panel {
private int panelWidth;
private int panelHeight;
private Image offscreenImage;
private Graphics offscreenGraphics;
public PanelDoubleBuffered() {
super();
}
@Override
public void update(final Graphics g) {
paint(g);
}
@Override
public void paint(final Graphics g) {
super.paint(g);
// checks the buffersize with the current panelsize
// or initialises the image with the first paint
if (panelWidth != getSize().width
|| panelHeight != getSize().height
|| offscreenImage == null || offscreenGraphics == null) {
resetBuffer();
}
if (offscreenGraphics != null) {
//this clears the offscreen image, not the onscreen one
offscreenGraphics.clearRect(0, 0, panelWidth, panelHeight);
//calls the paintbuffer method with
//the offscreen graphics as a param
paintBuffer(offscreenGraphics);
//we finaly paint the offscreen image onto the onscreen image
g.drawImage(offscreenImage, 0, 0, this);
}
}
private void resetBuffer() {
// always keep track of the image size
panelWidth = getSize().width;
panelHeight = getSize().height;
// clean up the previous image
if (offscreenGraphics != null) {
offscreenGraphics.dispose();
}
if (offscreenImage != null) {
offscreenImage.flush();
}
// create the new image with the size of the panel
offscreenImage = createImage(panelWidth, panelHeight);
offscreenGraphics = offscreenImage.getGraphics();
}
public void paintBuffer(final Graphics g) {
// in classes extended from this one, add something to paint here!
// always remember, g is the offscreen graphics
}
}
class AnimatedPanel extends PanelDoubleBuffered {
private int posX;
public AnimatedPanel() {
super();
posX = 0;
setBackground(Color.BLACK);
}
public void animateToTheRight() {
// this method can be called from everywhere, anytime (thread safe)
boolean dispatchThread = EventQueue.isDispatchThread();
if (dispatchThread) {
int w = getWidth();
posX++;
if (posX > w) {
posX = 0;
}
repaint();
} else {
EventQueue.invokeLater(new Runnable() {
public void run() {
animateToTheRight();
}
});
}
}
// ATTENTION: we don't touch update() and paint() anymore!
// we use paintbuffer() instead:
@Override
public void paintBuffer(final Graphics g) {
// g is the offscreen graphics
g.setColor(Color.WHITE);
g.drawString("doublebuffered", posX, 20);
}
}