雖然 Applet 已淘汰,但其動畫邏輯(雙緩衝、執行緒驅動、update/paint 分離)是 Swing/JavaFX 動畫基礎。
public class Cartoon extends Applet implements Runnable,將動畫邏輯放入 run()。start() 啟動執行緒,stop() 設為 null 讓 run() 迴圈結束。getImage(getCodeBase(), "0.jpg") 從同目錄載入圖片。paint(Graphics g):預設先清除背景再繪製,會造成閃爍。update(Graphics g):不清除背景,直接繪製當前影格區域,配合 clipRect 實現逐行掃描效果。repaint() 排程呼叫 update(),非立即執行。
import java.applet.Applet;
import java.awt.*;
public class Cartoon extends Applet implements Runnable {
Image img;
Thread animator;
int frameHeight = 150, currentY = 0;
String[] frames = {"0.jpg","1.jpg","2.jpg","3.jpg"};
int frameIdx = 0;
public void run() {
while (true) {
// 切換影格
img = getImage(getCodeBase(), frames[frameIdx]);
frameIdx = (frameIdx + 1) % frames.length;
// 逐行掃描進場動畫
currentY = frameHeight;
repaint(); // 觸發 update
try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
currentY = 0;
while (currentY < frameHeight) {
repaint();
try { Thread.sleep(50); } catch (InterruptedException ignored) {}
currentY += 4;
}
}
}
public void update(Graphics g) {
if (img != null) {
g.clipRect(0, 0, 150, currentY); // 僅繪製上方 currentY 高度
g.drawImage(img, 0, currentY - frameHeight, this);
}
}
public void start() {
if (animator == null) {
animator = new Thread(this);
animator.start();
}
}
public void stop() {
animator = null; // run() 迴圈檢查 animator==null 退出
}
}
// Swing Timer (EDT 安全)
Timer timer = new Timer(50, e -> { /* 更新狀態 */ repaint(); });
timer.start();
// JavaFX
AnimationTimer timer = new AnimationTimer() {
long last = 0;
@Override public void handle(long now) {
if (now - last >= 50_000_000) { /* 更新 */ last = now; }
}
};
timer.start();
Applet 已從 JDK 11 移除,新專案請直接使用 JavaFX 或 Swing。