2009-09-24 150 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”以更好地理解这些概念。