Swing对话框是如何工作的?

18

如果在Swing中打开一个对话框,例如JFileChooser,它的伪代码如下:

Swing事件线程 {
  创建对话框
  添加对话框关闭事件监听器 {
    returnValue = somethingFromDialog
  }
  显示对话框
  (等待直到关闭)
  返回returnValue
}

我的问题是:这怎么可能行得通?正如您所看到的,该线程在等待对话框关闭之前将被阻塞。这意味着Swing事件线程被阻塞。但是,人们可以与对话框交互,这据我所知需要运行此线程。

那么这是如何工作的?

2个回答

9
现有的事件分发线程被阻塞,因此Swing创建另一个线程来推送事件。在对话框的持续时间内,这就是事件分发线程。
Swing为泵送本地操作系统窗口消息创建了一个单独的本地线程。这与AWT事件线程是分开的。
在Windows上,您可以看到这些线程。
  "AWT-Windows"   - the native UI thread
  "AWT-EventQueue-0" - the current AWT event dispatch thread

编辑:踩负评是对的。这并不总是正确的,至少不是所有情况。

模态对话框通常会自己处理AWT事件。如果您运行以下代码

SwingUtilities.invokeAndWait(new Runnable()
{
    public void run()
    {
        JOptionPane.showInputDialog("hello");
    }
});

然后断点,查看线程,您将只看到一个EventQueue线程。JOptionPane的show()方法本身会推动事件。

Spin和Foxtrot这样的框架采用相同的方法 - 它们允许您在EDT上创建长时间运行的阻塞方法,但通过自己推动事件来保持事件流动。虽然Swing可以有多个分派线程(我确信早期版本的Swing是这种情况),但现在多核已经很常见,因此并发问题,特别是确保在一个线程上的更改正确发布到其他线程,意味着在当前实现中使用多个EDT会产生错误。请参见Multiple Swing event-dispatch threads


那解释了一些事情。我点赞了你的回答,但有人给两个都踩了 :-/ - Bart van Heukelom
编辑应该完全纠正信息,或删除不正确的信息。没有必要在别人阅读后注明“上述内容不正确”。SO的目标是建立高质量答案的知识库。 - Luke Usherwood
1
不会启动新线程;“暂停”的代码仍然留在调用堆栈中,而代码进入一个新的EDT事件处理循环,可以继续处理GUI事件、绘制窗口等。点击模态对话框的“确定”按钮会退出“内部”循环,然后原始代码可以继续执行。 - Luke Usherwood

6

这是AWT线程,而不是Swing的。

无论如何,AWT在show中运行调度循环。对于被阻止的窗口的输入事件会被阻塞。重绘事件、未被阻塞的窗口的事件和一般事件将像往常一样被分派。

您可以通过添加以下行来查看:

 Thread.dumpStack();

从命令行使用jstack或在应用程序的命令窗口中使用ctrl-\/ctrl-break,可以将模态对话框转换为事件处理,或更容易地进行转换。

Foxtrot库滥用了这一点,以提供更加过程化的(而不是事件驱动的)模型。当从应用程序EDT调用时,WebStart/Java PlugIn也会使用它来为JNLP服务和其他服务提供对话框。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接