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

Java Swing 動態顯示時間三種實作方案對比

     編輯:Java 程式設計入門

一、需求場景

在 Swing 介面即時顯示系統時間(格式 HH:mm:ss),每秒更新一次。核心挑戰:定時觸發 UI 更新,且不阻塞事件調度執行緒 (EDT)。

二、方案一:Timer + TimerTask(推薦)

public class TimeFrame extends JFrame {
    private JLabel displayArea;
    private static final int ONE_SECOND = 1000;

    public TimeFrame() {
        displayArea = new JLabel();
        add(new JLabel("CurrentTime: "), BorderLayout.WEST);
        add(displayArea, BorderLayout.CENTER);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(200, 70);
        setLocationRelativeTo(null); // 置中

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override public void run() {
                String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
                // Swing 元件更新必須在 EDT,TimerTask 執行緒非 EDT
                SwingUtilities.invokeLater(() -> displayArea.setText(time));
            }
        }, new Date(), ONE_SECOND);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TimeFrame().setVisible(true));
    }
}

優點:Timer 可共用多個 TimerTask,scheduleAtFixedRate 固定頻率執行,無累積誤差;注意:UI 更新必須用 SwingUtilities.invokeLater() 轉派到 EDT。

三、方案二:獨立 Thread + sleep(簡單但不推薦生產)

public class TimeFrame2 extends JFrame implements Runnable {
    private JLabel displayArea;

    public TimeFrame2() {
        displayArea = new JLabel();
        add(new JLabel("CurrentTime: "), BorderLayout.WEST);
        add(displayArea, BorderLayout.CENTER);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(200, 70);
        setLocationRelativeTo(null);
    }

    @Override public void run() {
        while (true) {
            String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
            SwingUtilities.invokeLater(() -> displayArea.setText(time));
            try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
        }
    }

    public static void main(String[] args) {
        TimeFrame2 frame = new TimeFrame2();
        frame.setVisible(true);
        new Thread(frame).start();
    }
}

缺點:每個時鐘佔一條執行緒,sleep 精度低、累積誤差大,難以統一管理。

四、方案三:ScheduledExecutorService(現代替代 Timer)

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
    String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
    SwingUtilities.invokeLater(() -> displayArea.setText(time));
}, 0, 1, TimeUnit.SECONDS);

優點:標準化執行緒池 API、支援關閉、異常處理更完善,Java 5+ 推薦取代 Timer。

五、進階:世界時鐘(多時區切換)

public class WorldClock extends JFrame {
    private JComboBox<String> zoneBox;
    private JLabel displayArea;
    private TimeZone currentZone = TimeZone.getDefault();

    public WorldClock() {
        zoneBox = new JComboBox<>(TimeZone.getAvailableIDs());
        zoneBox.addActionListener(e -> currentZone = TimeZone.getTimeZone(
            (String) zoneBox.getSelectedItem()));

        displayArea = new JLabel();
        add(zoneBox, BorderLayout.NORTH);
        add(displayArea, BorderLayout.CENTER);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack(); setLocationRelativeTo(null); setVisible(true);

        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
            SimpleDateFormat fmt = new SimpleDateFormat("EEE d MMM, HH:mm:ss", Locale.ENGLISH);
            fmt.setTimeZone(currentZone);
            String time = fmt.format(new Date());
            SwingUtilities.invokeLater(() -> displayArea.setText(time));
        }, 0, 1, TimeUnit.SECONDS);
    }
}

關鍵點:SimpleDateFormat 非執行緒安全,每次更新新建實例或用 ThreadLocal;TimeZone.getAvailableIDs() 取得所有时区 ID。

六、常用 Swing 技巧備忘

程式碼作用
setDefaultCloseOperation(EXIT_ON_CLOSE)關閉視窗結束 JVM
setLocationRelativeTo(null)視窗置中螢幕
pack()依元件優先尺寸自動計算視窗大小
SwingUtilities.invokeLater(Runnable)將 Runnable 排程到 EDT 執行(非 EDT 更新 UI 必須)

七、總結

  1. 首選 ScheduledExecutorService(或 Timer)定時任務,避免手動 Thread.sleep 循環。
  2. UI 更新務必轉派到 EDT,否則會出現競態條件、畫面閃爍或凍結。
  3. SimpleDateFormat 非執行緒安全,多執行緒環境每次新建或用 DateTimeFormatter (Java 8+)。
  4. 世界時鐘示範 JComboBox 動態切換 TimeZone,pack() 自適應版面。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved