早期 Java Applet 繪製動畫時,直接在 paint() 繪圖會產生嚴重閃爍,因為預設 update() 會先清除畫面再呼叫 paint()。
public class OnlyChangeUpdate extends Applet implements Runnable {
int x, y, dx=20, dy=20, w, h;
Thread t;
public void init() {
w = getSize().width; h = getSize().height;
setBackground(Color.black);
}
public void start() { t = new Thread(this); t.start(); }
public void stop() { t = null; }
public void paint(Graphics g) {
g.setColor(Color.white);
g.fillOval(x, y, 15, 15);
}
public void update(Graphics g) { paint(g); } // 取消預設清屏
public void run() {
while (t != null) {
repaint();
try { Thread.sleep(80); } catch (InterruptedException ignored) {}
x += dx; y += dy;
if (x >= w-15) { x = w-15; dx = -dx; }
if (x <= 0) { x = 0; dx = -dx; }
if (y >= h-15) { y = h-15; dy = -dy+5; }
if (y <= 0) { y = 0; dy = -dy+5; }
}
}
}
缺點:update() 仍會閃爍,碰撞邏輯含 +5 魔術數字,物理感不真實。
public class UseDoubleBuffering extends Applet implements Runnable {
int x, y, dx=2, dy=3, w, h;
Thread t;
Image offScreen;
Graphics offG;
public void init() {
w = getSize().width; h = getSize().height;
offScreen = createImage(w, h);
offG = offScreen.getGraphics();
}
public void start() { t = new Thread(this); t.start(); }
public void stop() { t = null; }
public void paint(Graphics g) {
offG.setColor(Color.black);
offG.fillRect(0, 0, w, h); // 離屏清屏
offG.setColor(Color.white);
offG.fillOval(x, y, 15, 15); // 離屏繪圖
g.drawImage(offScreen, 0, 0, this); // 一次性貼上螢幕
}
public void update(Graphics g) { paint(g); }
public void run() {
while (t != null) {
repaint();
try { Thread.sleep(50); } catch (InterruptedException ignored) {}
x += dx; y += dy;
if (x >= w-15) { x = w-15; dx = -dx; }
if (x <= 0) { x = 0; dx = -dx; }
if (y >= h-15) { y = h-15; dy = -dy; }
if (y <= 0) { y = 0; dy = -dy; }
}
}
}
createImage(w, h) 在記憶體建立一張畫布。offG,螢幕不見中間過程。g.drawImage(offScreen, 0, 0, this) 將完幀一次複製到顯示器,消除閃爍。Applet 已被瀏覽器淘汰。新專案請使用:
JPanel 覆寫 paintComponent(),預設即雙緩衝(setDoubleBuffered(true))。