Swingworker.done()在完成后冻结GUI几秒钟

Gig*_*ron 1 java swing multithreading swingworker event-dispatch-thread

我有一个SwingWorker,它在后台读取和处理文件,然后在JTextPane中格式化并显示各种样式的数据.

如果文件很大(超过200K),我将显示一个带进度条的对话框.在SwingWorker的done()方法中,我填充了JTextPane,然后隐藏了对话框.done()方法如下所示:

protected void done() {
   populateTextPane();

   hideProgressDialog();
   System.out.println("After hideProgressDialog");
}
Run Code Online (Sandbox Code Playgroud)

当它运行时,我将看到对话框消失,控制台上的println消息,但GUI再冻结10-15秒,数据在冻结结束时在JTextPane中可见.

我认为在done()方法中发生的任何事情都会发生在Event Dispatch Thread中.但显然JVM正在产生另一个线程来隐藏对话框并在填充JTextPane时执行println.我想保持显示进度对话框,直到GUI准备好再次接受用户输入...如何检测done()中的所有内容何时完成?

Rob*_*bin 6

done方法在EDT上执行.如果您对此表示怀疑,可以随时使用该EventQueue.isDispatchThread()方法进行检查.

可能的解释是该populateTextPane()方法计划JTextPane在EDT上重新绘制.这意味着done()在您populateTextPane()在UI中看到方法的结果之前,该方法已完成.

您可以尝试done按如下方式重写该方法

protected void done() {
   populateTextPane();
   SwingUtilities.invokeLater( new Runnable(){
     @Override
     public void run(){
       hideProgressDialog();
       System.out.println("After hideProgressDialog");
     }
   } );
}
Run Code Online (Sandbox Code Playgroud)

这将确保hideProgressDialog仅在EDT上的任何可能RunnablepopulateTextPane()时间表之后执行.但是,这仍然会冻结您的UI 10-15秒.唯一的区别是进度对话框仍然可见.

如果进度对话框显示在顶部,则不确定这是否有效JTextPane.该RepaintManager会决定只重绘JTextPane后的对话成为无形的(因此不再隐藏JTextPane).