我在 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
我错过了什么?我尝试在此处进行谷歌搜索,但没有真正看到任何明显的东西?
最佳答案
您必须在另一个线程中执行长时间运行的任务。
有一个名为“AWT Event Dispatch Thread”的线程,负责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”来更好地理解这些概念。
关于java - 强制 JFrame 刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1474221/