JDialog 关闭后滞后
JDialog lags after closing
在我的代码中,我初始化了一个 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 ) {
// ...
}
我的问题是,一旦我单击按钮 运行s dialog.setVisible( false )
:
- 对话框消失
- 框架完全冻结(进度条状态永远不会改变)
- 在控制台上出现消息"Successful login."后,帧仍然冻结
- 大约 10 秒过去后,框架终于重新绘制,我在
accountModel.login()
中调用的所有状态消息都出现在它上面
如何让我的主要 window 组件在登录代码为 运行ning 时响应?
如您所见,我已将所有内容封装在一个 SwingUtilities.invokeLater()
调用中,但这似乎根本没有帮助。
As you can see, I have the entire thing wrapped in a SwingUtilities.invokeLater() call,
这就是问题所在。 invokeLater() 将代码放在 EDT 上,这意味着 GUI 无法重新绘制自身或响应事件,直到长 运行 任务完成执行。
所以解决方案是为长 运行 任务使用单独的 Thread
,然后在 Thread
需要更新 GUI 时使用 invokeLater()
.
或者,您也可以使用 SwingWorker
来为您创建线程,然后您可以将代码添加到 SwingWorker 的 done()
方法来更新 GUI。
阅读有关 Concurrency 的 Swing 教程部分,了解有关 Event Dispatch Thread (EDT)
和 SwingWorker
的更多信息。
在我的代码中,我初始化了一个 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 ) {
// ...
}
我的问题是,一旦我单击按钮 运行s dialog.setVisible( false )
:
- 对话框消失
- 框架完全冻结(进度条状态永远不会改变)
- 在控制台上出现消息"Successful login."后,帧仍然冻结
- 大约 10 秒过去后,框架终于重新绘制,我在
accountModel.login()
中调用的所有状态消息都出现在它上面
如何让我的主要 window 组件在登录代码为 运行ning 时响应?
如您所见,我已将所有内容封装在一个 SwingUtilities.invokeLater()
调用中,但这似乎根本没有帮助。
As you can see, I have the entire thing wrapped in a SwingUtilities.invokeLater() call,
这就是问题所在。 invokeLater() 将代码放在 EDT 上,这意味着 GUI 无法重新绘制自身或响应事件,直到长 运行 任务完成执行。
所以解决方案是为长 运行 任务使用单独的 Thread
,然后在 Thread
需要更新 GUI 时使用 invokeLater()
.
或者,您也可以使用 SwingWorker
来为您创建线程,然后您可以将代码添加到 SwingWorker 的 done()
方法来更新 GUI。
阅读有关 Concurrency 的 Swing 教程部分,了解有关 Event Dispatch Thread (EDT)
和 SwingWorker
的更多信息。