Swing 对话框如何工作?

Posted

技术标签:

【中文标题】Swing 对话框如何工作?【英文标题】:How can Swing dialogs even work? 【发布时间】:2011-03-03 00:18:22 【问题描述】:

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

swing 事件线程 
  创建对话框
  将侦听器添加到对话框关闭事件 
    returnValue = somethingFromDialog
  
  显示对话框
  (等到它关闭)
  返回返回值

我的问题是:这怎么可能起作用?如您所见,线程等待返回,直到对话框关闭。这意味着 Swing 事件线程被阻塞。然而,人们可以与对话框进行交互,AFAIK 需要此线程运行。

那么它是如何工作的呢?

【问题讨论】:

【参考方案1】:

现有的事件调度线程被阻塞,因此 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");
    
);

然后break,查看线程,你会看到只有一个EventQueue线程。 JOptionPane 的 show() 方法自己泵送事件。

像Spin 和 Foxtrot 这样的框架采用相同的方法——它们允许您在 EDT 上创建一个长时间运行的阻塞方法,但通过泵送事件本身来保持事件的流动。 swing 可以有多个调度线程(我确信旧版本的 swing 就是这种情况),但现在多核很常见,并发问题,特别是确保一个线程上的更改正确发布到其他线程,意味着使用多个 EDT 会在当前实现中产生错误。看 Multiple Swing event-dispatch threads

【讨论】:

这就解释了。赞成您的答案,但其他人都反对:-/ 编辑应该完全更正信息,或删除不正确的信息。没有必要说明一些东西供其他人阅读,然后再指出“上述内容不正确”。 SO 的目的是建立一个高质量答案的知识库 没有新线程启动; “暂停”的代码保留在调用堆栈上,代码进入一个新的 EDT 事件处理循环,该循环可以继续处理 GUI 事件、绘制窗口等。 '确定'模式对话框退出“内部”循环,然后原始代码可以继续。【参考方案2】:

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

无论如何,AWT 在show 内运行调度循环。阻塞窗口的输入事件被阻塞。重绘事件、解锁窗口的事件和一般事件照常调度。

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

 Thread.dumpStack();

进入模式对话框的偶数处理,或者更容易从命令行使用jstack 或在应用程序的命令窗口中使用ctrl-\/ctrl-break

Foxtrot 库滥用它来提供更程序化(与事件驱动相反)的模型。当从应用程序 EDT 调用时,WebStart/Java 插件也使用它来为 JNLP 服务和其他服务提供对话框。

【讨论】:

以上是关于Swing 对话框如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用always-on-top对话框结束Swing程序?

非阻塞模式 Swing 进度对话框

Java在Swing中如何实现弹出一个对话框的效果?

JAVA Swing中如何实现一个非阻塞的对话框。

Java SWing中如何通过双击使子对话框从父窗口中弹出并嵌入到父窗口中?

我如何将javax.swing.ImageIcon绘制为JavaFX .fxml呈现的用户界面?