首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 線程控制動畫實戰:Swing 繪圖與雙緩衝技術

     編輯:Java 程式設計入門

核心概念

  • 線程:程序執行的最小單元,CPU 調度基本單位。動畫循環放入獨立線程,避免阻塞事件分發線程 (EDT)。
  • Runnable 接口:定義 run() 方法作為線程入口。
  • 雙緩衝繪圖:先在離屏圖像 (Image) 上繪製,再一次性繪製到屏幕,消除閃爍。

完整示例:彈跳小球動畫

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Cartoon extends JApplet implements Runnable {
    // 雙緩衝組件
    private Image offScreenImage;
    private Graphics offScreenGraphics;
    
    // 動畫線程
    private Thread animator;
    
    // 小球狀態
    private int x = 5;
    private int dx = 1; // 水平速度
    private static final int BALL_SIZE = 90;
    private static final int LEFT_WALL = 5;
    private static final int RIGHT_WALL = 105;

    @Override
    public void init() {
        // 創建離屏緩衝區
        offScreenImage = createImage(230, 160);
        offScreenGraphics = offScreenImage.getGraphics();
    }

    @Override
    public void start() {
        if (animator == null) {
            animator = new Thread(this);
            animator.start();
        }
    }

    @Override
    public void run() {
        Thread current = Thread.currentThread();
        while (animator == current) { // 線程未被替換則持續運行
            // 更新位置
            x += dx;
            if (x > RIGHT_WALL || x < LEFT_WALL) {
                dx = -dx; // 反向
            }
            repaint(); // 觸發重繪
            
            // 幀率控制 (~60 FPS)
            try { Thread.sleep(16); } catch (InterruptedException ignored) {}
        }
    }

    private void drawBall(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        // 背景雙色分割
        g2d.setColor(Color.BLUE);
        g2d.fillRect(0, 0, 100, 100);
        g2d.setColor(Color.YELLOW);
        g2d.fillRect(100, 0, 100, 100);
        // 繪製小球
        g2d.setColor(Color.RED);
        g2d.fillOval(x, 5, BALL_SIZE, BALL_SIZE);
    }

    @Override
    public void paint(Graphics g) {
        // 1. 清空離屏緩衝
        offScreenGraphics.setColor(Color.WHITE);
        offScreenGraphics.fillRect(0, 0, 230, 160);
        
        // 2. 在離屏繪製動畫幀
        drawBall(offScreenGraphics);
        
        // 3. 一次性繪製到屏幕
        g.drawImage(offScreenImage, 130, 100, this);
    }
}

關鍵技術點解析

1. 動畫線程生命週期管理

  • start():Applet 可見時啟動線程。
  • stop():建議補充,Applet 不可見時停止線程,釋放 CPU。
    public void stop() {
        animator = null; // run() 循環條件失效,線程自然結束
    }

2. 雙緩衝消除閃爍

  1. createImage(w, h) 創建離屏 Image。
  2. image.getGraphics() 獲取離屏繪圖上下文。
  3. 所有繪圖操作針對離屏 Graphics。
  4. g.drawImage(offScreenImage, x, y, this) 一次性拷貝到屏幕。

3. 幀率控制

Thread.sleep(16) 約等於 60 FPS。實際項目可用 javax.swing.Timer 或 java.util.Timer 替代手動睡眠,精度更高、更易暫停/恢復。

現代化改進建議

  • 改用 JPanel + paintComponent() 替代 Applet(Applet 已被移除)。
  • 使用 BufferStrategy (全屏獨占模式) 或 VolatileImage 獲得硬件加速。
  • 遊戲迴圈採用 固定時間步長 分離邏輯更新與渲染。
  • 引入 javafx.animation.AnimationTimer (JavaFX) 獲得更流暢的動畫支持。

總結

本例演示了 Java 線程驅動動畫的經典模式:獨立線程更新狀態 → 雙緩衝繪圖 → 觸發重繪。雖然 Applet 已成歷史,但核心思想(線程隔離、雙緩衝、幀率控制)在 Swing、JavaFX、LibGDX 等現代圖形框架中依然通用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved