我有一个SwingWorker,它在后台读取和处理文件,然后在JTextPane中格式化并显示各种样式的数据。
如果文件很大(超过200K),我将显示一个带进度条的对话框。在SwingWorker的done()方法中,我填充了JTextPane,然后隐藏了对话框。 done()方法如下所示:
protected void done() {
populateTextPane();
hideProgressDialog();
System.out.println("After hideProgressDialog");
}
当它运行时,我会在控制台看到对话框消失和println消息,但GUI再冻结10-15秒,数据在冻结结束时在JTextPane中可见。 / p>
我认为在done()方法中发生的任何事情都会发生在Event Dispatch Thread中。但显然JVM正在产生另一个线程来隐藏对话框并在填充JTextPane时执行println。我希望显示进度对话框,直到GUI准备再次接受用户输入...如何检测done()中的所有内容何时完成?
答案 0 :(得分:6)
{1}}方法在EDT上执行。如果您对此表示怀疑,可以随时使用done
方法进行检查。
可能的解释是EventQueue.isDispatchThread()
方法计划在EDT上重新绘制populateTextPane()
。这意味着在您在用户界面中看到JTextPane
方法的结果之前,done()
方法已完成。
您可以尝试重写populateTextPane()
方法,如下所示
done
这将确保protected void done() {
populateTextPane();
SwingUtilities.invokeLater( new Runnable(){
@Override
public void run(){
hideProgressDialog();
System.out.println("After hideProgressDialog");
}
} );
}
仅在EDT上任何可能的hideProgressDialog
Runnable
日程表之后执行。但是,这仍然会冻结您的UI 10-15秒。唯一的区别是进度对话框仍然可见。
如果进度对话框显示在populateTextPane()
之上,则不确定这是否有效。 JTextPane
可能决定仅在对话框不可见后重新显示RepaintManager
(因此不再隐藏JTextPane
)。
答案 1 :(得分:1)
听起来像populateTextPane是EDT上一个长期运行的过程 - 你不想要它。尝试将其拆分:SwingWorker支持发布中间结果。
像
这样的东西@Override
public Void doInBackground() throws Exception {
...
while (!reader.isReady()) {
publish(reader.readLine());
}
return null;
}
@Override
protected void process(List<String> lines) {
for(String line: lines) {
textPane.append(line);
}
}