Swing 对话框如何工作?
如果您在 Swing 中打开一个对话框,例如 JFileChooser,它有点像这样的伪代码:
swing event thread { create dialog add listener to dialog close event { returnValue = somethingFromDialog } show dialog (wait until it is closed) return returnValue }
我的问题是:这怎么可能工作?正如您所看到的,线程等待返回,直到对话框关闭。这意味着 Swing 事件线程被阻塞。然而,人们可以与对话框进行交互,据我所知,这需要该线程来运行。
那么它是如何运作的呢?
If you open a dialog in Swing, for example a JFileChooser, it goes somewhat like this pseudocode:
swing event thread { create dialog add listener to dialog close event { returnValue = somethingFromDialog } show dialog (wait until it is closed) return returnValue }
My question is: how can this possibly work? As you can see the thread waits to return until the dialog is closed. This means the Swing event thread is blocked. Yet, one can interact with the dialog, which AFAIK requires this thread to run.
So how does that work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
现有的事件调度线程被阻塞,因此 swing 创建另一个泵送事件的线程。这是对话期间的事件调度线程。
Swing 创建一个单独的本机线程来泵送本机操作系统窗口消息。这与 AWT 事件线程是分开的。
在 Windows 上,您会看到这些线程
编辑:否决是正确的。这不是真的,至少不是在所有情况下都是如此。
模态对话框通常负责泵送 AWT 事件本身。如果运行代码
然后中断,查看线程,您将只看到一个 EventQueue 线程。 JOptionPane 的 show() 方法泵送事件本身。
像 Spin 和 Foxtrot 这样的框架采用相同的方法 - 它们允许您在 EDT 上创建长时间运行的阻塞方法,但通过泵送事件本身来保持事件的流动。 swing 可能有多个调度线程(我确信旧版本的 swing 就是这种情况),但现在多核很常见,并发问题,特别是确保一个线程上的更改正确发布到其他线程,意味着使用多个 EDT 会在当前实现中产生错误。看
多个 Swing 事件调度线程
The existing event dispatch thread is blocked, and so swing creates another thread that pumps the events. This is then the event dispatch thread for the duration of the dialog.
Swing creates a separate native thread for pumping native OS window messages. This is separate from the AWT event thread.
On Windows, you see these threads
EDIT: The downvote is correct. This is not true, at least not in all cases.
Modal dialogs often take care of pumping AWT events themselves. If you run the code
and then break, looking at the threads, you will see only one EventQueue thread. The show() method of JOptionPane pumps events itself.
Frameworks like Spin and Foxtrot take the same approach - they allow you to create a long running blocking method on the EDT, but keep the events flowing by pumping events themselves. It is possible for swing to have multiple dispatch threads (I'm sure this was the case with older versions of swing) but now that multicore is common, the concurrency issues, in particular ensuring changes on one thread are correctly published to other threads, mean that using multiple EDTs produces bugs in the current implementation. See
Multiple Swing event-dispatch threads
这是 AWT 的线程,而不是 Swing 的线程。
不管怎样,AWT 在
show
中运行调度循环。阻止窗口的输入事件将被阻止。重绘事件、解锁窗口事件和一般事件照常调度。您可以通过将行:添加
到模式对话框的偶数处理中来看到这一点,或者更容易地从命令行使用
jstack
或使用ctrl-\
/ctrl-break
在应用程序的命令窗口中。Foxtrot 库滥用这一点来提供更加程序化(而不是事件驱动)的模型。当从应用程序 EDT 调用时,WebStart/Java PlugIn 也使用它为 JNLP 服务和其他服务提供对话框。
It's the AWT's thread, not Swing's.
Anyway, AWT runs the dispatch loop within the
show
. Input events to blocked windows are blocked. Repaint events, events to unblocked windows and general events are dispatched as usual.You can see this either by adding the line:
into the even handling for the modal dialog, or more easily from the command line with
jstack
or usectrl-\
/ctrl-break
in the command window of the application.The Foxtrot library abuses this to provide a more procedural (as opposed to event-driven) model. It's also used by WebStart/Java PlugIn to provide dialogs for JNLP services and others when called from the application EDT.