关闭后JDialog滞后

时间:2016-01-05 03:22:00

标签: java swing jdialog invokelater

在我的代码中,我初始化了一个JDialog:

dialog = new JDialog( frame, "Login", true );
dialog.setContentPane( panel );
dialog.setDefaultCloseOperation( JDialog.HIDE_ON_CLOSE );
dialog.setBounds( new Rectangle( 50, 50, 500, 500 ) );

当我点击主应用程序中的按钮时,我会显示该对话框,然后使用我从中获得的数据运行一个昂贵的方法:

dialogWrapper.show(); // Runs dialog.setVisible( true ) directly
LoginCredentials credentials = dialogWrapper.getCredentials(); // Gets data from dialog
try {
    SwingUtilities.invokeLater( new Runnable() {
        @Override
        public void run() {
            progressBar.setIndeterminate( true );
            mainWindow.getFrame().repaint();
            accountModel.login( credentials );
            System.out.println( "Successful login." );
            mainWindow.getFrame().revalidate();
            mainWindow.getFrame().repaint();
            progressBar.setIndeterminate( false );
        }
    } );
} catch ( Exception ex ) {
    // ...
}

我的问题是,只要我点击运行dialog.setVisible( false )的按钮:

  • 对话框消失
  • 框架完全冻结(进度条状态不会改变)
  • 在“成功登录”消息之后。出现在控制台上,框架仍然被冻结
  • 大约10秒钟后,框架最终重新绘制,我在accountModel.login()的一部分调用的所有状态消息都显示在其上

如何在登录代码运行时使我的主窗口组件响应?

正如您所看到的,我将整个事情包含在SwingUtilities.invokeLater()电话中,但这似乎没有任何帮助。

1 个答案:

答案 0 :(得分:2)

  

正如您所看到的,我将整个事件包含在SwingUtilities.invokeLater()调用中,

这就是问题所在。 invokeLater()将代码放在EDT上,这意味着GUI不能重新绘制对事件的响应,直到长时间运行的任务完成执行为止。

因此,解决方案是为长时间运行的任务使用单独的Thread,然后在需要更新GUI时在Thread中使用invokeLater()

或者,您也可以使用SwingWorker为您创建线程,然后您可以将代码添加到SwingWorker的done()方法以更新GUI。

阅读Concurrency上Swing教程中的部分,了解有关Event Dispatch Thread (EDT)SwingWorker的更多信息。