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

Java Swing 跑馬燈程式實作:Timer 驅動動畫與元件繪製入門

     編輯:Java 相關知識

程式功能

  • 顯示當前日期時間跑馬燈
  • 自訂字型、顏色、速度
  • 展示 Swing 繪圖、Timer、自訂元件基礎

完整程式碼

package clock;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Calendar;
import java.util.Date;
import java.text.*;

public class RunningLight extends JFrame {
    
    public RunningLight() {
        // 字型設定
        Font font = new Font("微軟正黑體", Font.BOLD, 16);
        
        // 日期時間格式化
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat formatter = new SimpleDateFormat(
            "EEEE, MMMM dd日, yyyy年 HH:mm:ss", Locale.TRADITIONAL_CHINESE);
        String dateTime = formatter.format(cal.getTime());
        
        // 自訂跑馬燈面板
        MovingMessagePanel panel = new MovingMessagePanel(dateTime);
        panel.setFont(font);
        panel.setBackground(Color.BLACK);
        panel.setForeground(Color.PINK);
        
        add(panel);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            RunningLight frame = new RunningLight();
            frame.setTitle("Java Swing 跑馬燈示範");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400, 150);
            frame.setLocationRelativeTo(null); // 置中
            frame.setVisible(true);
        });
    }
    
    // 內部類:跑馬燈面板
    static class MovingMessagePanel extends JPanel {
        private String message = " ";
        private int x = 0;
        private final int y = 40;
        
        public MovingMessagePanel(String message) {
            this.message = message;
            // 每 100ms 觸發重繪
            Timer timer = new Timer(100, new TimerListener());
            timer.start();
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); // 清除背景
            
            // 文字超出寬度 → 重置到左側外部
            if (x > getWidth()) {
                x = -100; // 文字寬度估值
            }
            x += 5; // 每幀移動 5 像素
            
            g.drawString(message, x, y);
        }
        
        // Timer 事件監聽
        class TimerListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint(); // 觸發 paintComponent
            }
        }
    }
}

核心技術點解析

技術說明關鍵代碼
自訂繪圖繼承 JPanel,覆寫 paintComponentg.drawString(message, x, y)
動畫循環javax.swing.Timer 定時觸發 repaintnew Timer(100, listener).start()
雙重緩衝JPanel 預設開啟,無閃爍無需額外代碼
EDT 安全主程式用 invokeLater,Timer 事件在 EDTSwingUtilities.invokeLater
資源釋放關閉視窗自動停止 (EXIT_ON_CLOSE)Timer 需手動 stop() 更嚴謹

改進版:支援動態文字、暫停/繼續、速度調整

static class AdvancedMovingPanel extends JPanel {
    private String message = " ";
    private int x = 0;
    private int speed = 5;
    private int delay = 100;
    private Timer timer;
    private boolean running = true;
    
    public AdvancedMovingPanel(String message) {
        this.message = message;
        timer = new Timer(delay, e -> {
            if (running) repaint();
        });
        timer.start();
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        FontMetrics fm = g.getFontMetrics();
        int textWidth = fm.stringWidth(message);
        
        if (x > getWidth()) x = -textWidth;
        x += speed;
        g.drawString(message, x, 40);
    }
    
    public void setMessage(String msg) { this.message = msg; }
    public void setSpeed(int pxPerFrame) { this.speed = pxPerFrame; }
    public void setDelay(int ms) { timer.setDelay(ms); }
    public void pause() { running = false; }
    public void resume() { running = true; }
    public void stop() { timer.stop(); }
}

常見問題與解決

  1. 中文顯示方塊:字型不支援中文 → 使用「微軟正黑體」、「新細明體」、「Noto Sans CJK TC」等
  2. 閃爍:未呼叫 super.paintComponent(g) 或關閉雙重緩衝
  3. CPU 佔用高:Timer 延遲設太小 (如 1ms) → 建議 50-100ms
  4. 文字速度不均:GC 導致 Timer 延遲 → 可用 System.nanoTime() 計算實際位移

現代替代:JavaFX 動畫

// JavaFX 更流暢、GPU 加速、聲明式
Timeline timeline = new Timeline(
    new KeyFrame(Duration.millis(16), e -> {
        // 更新位移
        text.setX(text.getX() + 2);
        if (text.getX() > width) text.setX(-textWidth);
    })
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();

總結

Swing 跑馬燈展示了自訂元件 + Timer 動畫 + EDT 繪圖的經典模式。雖 Swing 屬維護模式,但理解其繪圖機制、事件模型、執行緒規則,對維護舊系統、學習 GUI 基礎仍有價值。新專案建議使用 JavaFX 或 Web 技術棧。

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