經典 Java 圖形程式教學範例:使用 Applet、Thread、MediaTracker、雙緩衝(createImage)繪製可換膚、可調指針顏色、含跑馬燈字幕的類比時鐘。雖然 Applet 已棄用,但繪圖邏輯、雙緩衝模式、執行緒協同仍具參考價值,可移植至 Swing/JavaFX。
Image offscreen = createImage(w, h); Graphics g = offscreen.getGraphics(); 先畫離屏再 drawImage(offscreen, 0, 0, this),消除閃爍。repaint() 更新指針角度。x = cx + r * sin(angle), y = cy - r * cos(angle)(y 軸向下)。drawImage 失敗。// 雙緩衝初始化
offscreenImage = createImage(getWidth(), getHeight() - 35);
offscreenGraphics = offscreenImage.getGraphics();
// 背景繪製執行緒 (thread2)
class BackgroundPainter implements Runnable {
public void run() {
while (true) {
offscreenGraphics.setColor(Color.WHITE);
offscreenGraphics.fillRect(0, 0, width, height);
offscreenGraphics.drawImage(backgroundImg, 110, 100, this);
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
}
}
}
// 指針更新執行緒 (主 run)
public void run() {
while (true) {
try { Thread.sleep(1000); repaint(); } catch (InterruptedException ignored) {}
}
}
// paint() 僅負責將離屏圖貼上並畫指針/文字
public void paint(Graphics g) {
g.drawImage(offscreenImage, 0, 0, this);
// 計算時/分/秒角度
// 畫三條指針
g.drawString(timeStr, 150, 100);
// 畫跑馬燈字幕
}
JPanel 覆寫 paintComponent(Graphics g),放入 JFrame 或 JApplet(同樣已棄用)。javax.swing.Timer 替代手動 Thread.sleep,確保事件派發執行緒 (EDT) 安全。Canvas + AnimationTimer 實現更流暢動畫,支援 GPU 加速。ImageIO.read() 或 getClass().getResource(),移除 MediaTracker。public class Clock extends Applet implements Runnable, ActionListener, MouseListener {
// 欄位:Image、Graphics、Thread、顏色、按鈕、字幕陣列...
public void init() { /* UI 初始化、圖片載入、雙緩衝建立、啟動執行緒 */ }
public void start() { /* 啟動三條執行緒 */ }
public void paint(Graphics g) { /* 離屏貼圖 + 指針 + 文字 */ }
public void update(Graphics g) { paint(g); } // 避免預設清屏閃爍
public void run() { /* 秒級 repaint */ }
// 內部類 BackgroundPainter, MarqueeThread
// ActionListener 處理顏色/皮膚選擇
// MouseListener 除錯用
}
此範例展示了 Java 2D 繪圖、多執行緒動畫、資源管理、事件處理的綜合運用,是理解 Java 客戶端圖形編程基礎的優秀教材。