2009-09-24 118 views
1

我有一個內置JFrame的UI。其中一個按鈕開始一個長時間的運行調用(仍在同一個java進程中),並且在執行期間,UI被凍結。強制JFrame刷新

我想,爲了清楚事情還在進行中,我可以在彈出窗口中顯示進度條,以便用戶可以隨時瞭解程序正在執行的操作。

所以我創建了一個新的JDialog,添加了一個JProgressBar對象,並在事件發生時更新它。問題是該對話框的內容沒有得到更新。我對它的標題所做的更改立即顯示出來,以及我輸出到控制檯的任何內容,但是UI本身沒有任何內容。

是否有一個命令我可以強制重繪?

下面是本節的核心:

killWindow = new JDialog(); 
    killWindow.setUndecorated(true); 
    killWindow.setTitle("stopping tests - 0 of " + numActive); 
    killProgress = new JProgressBar(0, numActive); 
    killWindow.add(killProgress); 
    killProgress.setStringPainted(true); 
    killWindow.pack(); 
    killWindow.setLocationRelativeTo(frame); 
    killWindow.setVisible(true); 

然後,當我們進步...:

killProgress.setValue(++killedTests);     // not seen! 
    killProgress.setString("Killing test on " + nickname()); // not seen! 
    log("Killed another test, " + killedTests + " so far"); // visible in real time 
    killWindow.setTitle("stopping tests - " + killedTests + 
         " of " + killProgress.getMaximum()); // visible in real time 

我缺少什麼?我試着在Google上搜索並搜索,並沒有真正看到任何明顯的東西?

回答

3

您必須在另一個線程中執行長時間運行的任務。

有一個叫做「AWT Event Dispatch Thread」的線程負責UI組件的更新。如果它正忙於執行長時間運行的任務,那麼將不會更新UI(也不會刷新您的對話框)

您可以考慮使用SwingUtilitiesSwingWorker

從SwingWorker的documentation這裏有一個樣本

final JLabel label; 
class MeaningOfLifeFinder extends SwingWorker<String, Object> { 
    @Override 
    public String doInBackground() { 
     return findTheMeaningOfLife(); 
    } 

    @Override 
    protected void done() { 
     try { 
      label.setText(get()); 
     } catch (Exception ignore) { 
     } 
    } 
} 

(new MeaningOfLifeFinder()).execute(); 

通過運行的長期任務在不同的線程,你讓AWT事件調度線程展現一個負責任的UI。

你可以看看這個「Lesson from the Java tutorial」以更好地理解這些概念。