我在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
我错过了什么?我试着谷歌搜索和搜索这里,并没有真正看到任何明显的东西?
答案 0 :(得分:3)
您必须在另一个线程中执行长时间运行的任务。
有一个名为“AWT Event Dispatch Thread”的线程负责UI组件的更新。如果忙于执行长时间运行的任务,将不会更新UI(也不会刷新对话框)。
您可以考虑使用SwingUtilities或SwingWorker。
从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
如果没有,您可以在以下网址找到更多信息: