在我的代码中,我初始化了一个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 )
的按钮:
accountModel.login()
的一部分调用的所有状态消息都显示在其上如何在登录代码运行时使我的主窗口组件响应?
正如您所看到的,我将整个事情包含在SwingUtilities.invokeLater()
电话中,但这似乎没有任何帮助。
答案 0 :(得分:2)
正如您所看到的,我将整个事件包含在SwingUtilities.invokeLater()调用中,
这就是问题所在。 invokeLater()将代码放在EDT上,这意味着GUI不能重新绘制对事件的响应,直到长时间运行的任务完成执行为止。
因此,解决方案是为长时间运行的任务使用单独的Thread
,然后在需要更新GUI时在Thread
中使用invokeLater()
。
或者,您也可以使用SwingWorker
为您创建线程,然后您可以将代码添加到SwingWorker的done()
方法以更新GUI。
阅读Concurrency上Swing教程中的部分,了解有关Event Dispatch Thread (EDT)
和SwingWorker
的更多信息。