Swing对话框如何工作?
如果你在Swing中打开一个对话框,例如一个JFileChooser,它就像这个伪代码:
swing事件线程{ 创建对话框 将侦听器添加到对话框关闭事件{ returnValue = somethingFromDialog } 显示对话框 (等到它关闭) return returnValue }
我的问题是:这怎么可能有效? 如您所见,线程等待返回,直到对话框关闭。 这意味着Swing事件线程被阻止。 然而,人们可以与对话框进行交互,AFAIK需要该对话框才能运行。
那怎么办?
这是AWT的主题,而不是Swing的主题。
无论如何,AWT在show
运行调度循环。 被阻止的窗口的输入事件被阻止。 像往常一样调度重新绘制事件,事件到未阻止的窗口和一般事件。
您可以通过添加以下行来查看:
Thread.dumpStack();
进入modal dialog的均匀处理,或者更容易从命令行使用jstack
或在应用程序的命令窗口中使用ctrl-\
/ ctrl-break
。
Foxtrot库滥用它来提供更多程序(而不是事件驱动)模型。 当从应用程序EDT调用时,WebStart / Java PlugIn也使用它来为JNLP服务和其他服务提供对话框。
现有的事件派发线程被阻止,因此swing创建另一个泵送事件的线程。 这是对话期间的事件派发线程。
Swing创建了一个单独的本机线程,用于抽取本机OS窗口消息。 这与AWT事件线程是分开的。
在Windows上,您可以看到这些线程
"AWT-Windows" - the native UI thread "AWT-EventQueue-0" - the current AWT event dispatch thread
编辑:downvote是正确的。 事实并非如此,至少在所有情况下都是如此。
modal dialog通常会自行处理AWT事件。 如果您运行代码
SwingUtilities.invokeAndWait(new Runnable() { public void run() { JOptionPane.showInputDialog("hello"); } });
然后打破,看看线程,你只会看到一个EventQueue线程。 JOptionPane的show()方法泵送事件本身。
像Spin和Foxtrot这样的框架采用相同的方法 – 它们允许您在EDT上创建一个长时间运行的阻塞方法,但通过抽取事件本身来保持事件流动。 swing可能有多个调度线程(我确信这是旧版本swing的情况)但现在多核是常见的,并发问题,特别是确保一个线程上的更改被正确发布到其他线程,意味着使用多个EDT会在当前实现中产生错误。 请参阅多个Swing事件派发线程