本文完整展示如何使用 Java Swing 構建一個可調速的多球彈跳動畫。專案涵蓋視窗建立、自訂繪圖畫布、定時器驅動動畫迴圈、鍵盤/滑鼠事件處理、焦點管理與動態速度調整等核心 GUI 程式設計技術。
JFrame,包含畫布區域與南部控制面板(JSpinner 調整延遲)Canvas,實作 ActionListener(定時器回調)與 FocusListener(焦點控制動畫暫停/恢復)public class BallsJFrame extends JFrame implements ChangeListener {
private BallsCanvas ball;
private JSpinner spinner;
public BallsJFrame() {
super("彈跳球動畫");
setBounds(300, 200, 400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Color[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA, Color.CYAN};
ball = new BallsCanvas(colors, 100); // 初始延遲 100ms
add(ball, BorderLayout.CENTER);
JPanel controlPanel = new JPanel();
controlPanel.add(new JLabel("延遲(ms):"));
spinner = new JSpinner();
spinner.setValue(100);
spinner.addChangeListener(this);
controlPanel.add(spinner);
add(controlPanel, BorderLayout.SOUTH);
setVisible(true);
}
@Override
public void stateChanged(ChangeEvent e) {
int delay = (Integer) spinner.getValue();
ball.setDelay(delay); // 動態調整定時器間隔
}
}
class BallsCanvas extends Canvas implements ActionListener, FocusListener {
private Ball[] balls;
private Timer timer; // javax.swing.Timer - 事件派發執行緒安全
public BallsCanvas(Color[] colors, int delay) {
balls = new Ball[colors.length];
for (int i = 0, x = 40; i < colors.length; i++, x += 20) {
balls[i] = new Ball(x, x, colors[i]);
}
addFocusListener(this); // 監聽焦點控制動畫
timer = new Timer(delay, this);
timer.start();
}
public void setDelay(int delay) {
timer.setDelay(delay);
}
@Override
public void paint(Graphics g) {
for (Ball ball : balls) {
g.setColor(ball.color);
// 更新 X 座標
ball.x = ball.left ? ball.x - 10 : ball.x + 10;
// 邊界檢測與反彈
if (ball.x <= 0 || ball.x >= getWidth() - 24) {
ball.left = !ball.left;
}
// 更新 Y 座標
ball.y = ball.up ? ball.y - 10 : ball.y + 10;
if (ball.y <= 0 || ball.y >= getHeight() - 22) {
ball.up = !ball.up;
}
g.fillOval(ball.x, ball.y, 20, 20);
}
}
@Override
public void actionPerformed(ActionEvent e) {
repaint(); // 觸發 paint() 重繪
}
@Override
public void focusGained(FocusEvent e) {
timer.stop(); // 失去焦點暫停
}
@Override
public void focusLost(FocusEvent e) {
timer.restart(); // 獲得焦點恢復
}
private static class Ball {
int x, y;
boolean up, left;
Color color;
public Ball(int x, int y, Color color) {
this.x = x; this.y = y; this.color = color;
up = left = false; // 初始向右下移動
}
}
}
| 技術點 | 實現方式 | 優勢 |
|---|---|---|
| 動畫驅動 | javax.swing.Timer | EDT 執行緒安全,自動處理重繪併發 |
| 雙緩衝 | Canvas 原生支援 / 可升級 JPanel | 消除閃爍 |
| 速度控制 | JSpinner + Timer.setDelay() | 即時動態調整,無需重建定時器 |
| 焦點管理 | FocusListener + timer.stop/restart | 視窗非活躍時節省 CPU |
| 邊界反彈 | 座標邊界檢測 + 方向布林旗標 | 邏輯簡單高效 |
Canvas 升級為 JPanel 並覆寫 paintComponent,獲得更好的雙緩衝支援Velocity 向量類別取代布林旗標,支援任意角度與速度大小BufferStrategy 實現主動式渲染,進一步提升幀率穩定性此專案展示了 Java Swing 建構互動式動畫應用的完整範式,從模型分離、事件驅動、執行緒安全到使用者體驗細節,是 GUI 程式設計入門與進階的優質實戰教材。