首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Swing/AWT:按鈕點擊後UI不刷新?正確使用SwingWorker避免阻塞EDT

     編輯:程式設計綜合問答

在Swing應用程式中,按鈕事件處理器若直接呼叫Thread.sleep(3000)或執行耗時任務,會阻塞事件派發執行緒(EDT),導致setText()、repaint()、validate()皆無法即時更新畫面,使用者看不到「正在清空...」提示,直接卡住3秒後跳到結果。本文說明正確的非同步處理模式。

錯誤示範(阻塞EDT)

outPrint.setText("其他地方數據正在清空...");
outPrint.repaint(); // 無效,EDT被佔用無法重繪
outPrint.validate(); // 無效
try {
    Thread.sleep(3000); // 災難:阻塞EDT,整個UI凍結
} catch (InterruptedException e1) {
    e1.printStackTrace();
}

正確做法:將耗時任務移至背景執行緒

outPrint.setText("其他地方數據正在清空...");

// 方案一:匿名Thread(簡單案例適用)
new Thread(() -> {
    try {
        // 執行耗時操作:清空資料、呼叫Web Service、大量運算等
        Thread.sleep(3000); // 模擬耗時
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        // 必須回到EDT更新UI
        SwingUtilities.invokeLater(() -> 
            outPrint.setText("清空完畢")
        );
    }
}).start();

進階做法:SwingWorker(可取消、進度回報、例外處理)

new SwingWorker<Void, Integer>() {
    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 0; i <= 100; i += 10) {
            Thread.sleep(300); // 模擬分階段任務
            publish(i); // 發布進度
            if (isCancelled()) break;
        }
        return null;
    }

    @Override
    protected void process(List<Integer> chunks) {
        // 在EDT中接收進度更新UI
        outPrint.setText("清空進度: " + chunks.get(chunks.size()-1) + "%");
    }

    @Override
    protected void done() {
        try {
            get(); // 拋出doInBackground中的例外
            outPrint.setText("清空完畢");
        } catch (Exception e) {
            outPrint.setText("失敗: " + e.getMessage());
        }
    }
}.execute();

核心原則總結

  1. EDT只負責UI更新與事件分派,任何可能超過50ms的操作都必須移出EDT。
  2. 背景執行緒不可直接操作Swing元件,必須透過SwingUtilities.invokeLater()、SwingWorker.publish/process、或EventQueue.invokeLater()回到EDT。
  3. repaint()、revalidate()只是排程重繪,若EDT被阻塞,重繪永遠不會執行。

掌握SwingWorker模式,即可優雅解決所有「長按鈕操作導致UI凍結」的問題。

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