强制JFrame刷新

时间:2009-09-24 21:21:33

标签: java refresh jframe

我在JFrame中内置了一个UI。其中一个按钮启动一个长时间运行的调用(仍然在同一个java进程中),并且在执行期间,UI被冻结。

我想,为了清楚地知道事情仍然在运行,我可以在弹出窗口中显示一个进度条,以便用户可以及时了解程序正在做什么。

所以我正在创建一个新的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

我错过了什么?我试着谷歌搜索和搜索这里,并没有真正看到任何明显的东西?

2 个答案:

答案 0 :(得分: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”以更好地理解这些概念。

答案 1 :(得分:1)

听起来您可能正在运行事件调度线程(EDT)上的长时间运行任务。看看SwingWorker。如果你使用1.6它是内置的:

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html

如果没有,您可以在以下网址找到更多信息:

http://en.wikipedia.org/wiki/SwingWorker