SwingUtilities.invokeLater
Posted
技术标签:
【中文标题】SwingUtilities.invokeLater【英文标题】: 【发布时间】:2011-11-04 01:02:22 【问题描述】:我的问题与 有关。我应该什么时候使用它?每次需要更新 GUI 组件时都必须使用吗?它究竟是做什么的?是否有替代方案,因为它听起来不直观并且添加了看似不必要的代码?
【问题讨论】:
相当于Control.BeginInvoke
。
@SLaks 这是否意味着如果我有一个线程我就不必使用它?
@FadelMS,由于 Swing 框架产生了它自己的线程(EDT),因此您将始终拥有该线程。 (你没有处理用户点击等的“消息检查”循环,对吧?那么各种 actionPerformed
方法是如何被调用的?由 EDT!)所以当你假设您有 一个 线程,我不得不解释一下,因为您 only 拥有 EDT(即,您抛出了一个 GUI 并从 main 方法的边缘掉了下来) .在这种情况下,不,您不会需要使用invokeLater
。但是,您将无法进行任何“后台”处理。如果这样做,您将完全锁定 GUI...
What does do? 的可能重复项
【参考方案1】:
每次需要更新 GUI 组件时都必须使用吗?
不,如果您已经在事件调度线程 (EDT) 上,则不会,这在响应用户发起的事件(例如点击和选择)时总是如此。 (actionPerformed
方法等总是由 EDT 调用。)
但是,如果您不是在 EDT 上并且想要进行 GUI 更新(如果您想从某个计时器线程或某个网络线程等更新 GUI),您将拥有安排由 EDT 执行的更新。这就是这个方法的用途。
Swing 基本上是线程不安全的。即,与该 API 的所有交互都需要在单个线程(EDT)上执行。如果您需要从另一个线程(计时器线程、网络线程...)进行 GUI 更新,您需要使用您提到的方法(SwingUtilities.invokeLater、SwingUtilities.invokeAndWait...)。
【讨论】:
@Jens:这意味着如果我在同一个线程(Swing)上或在运行时做事,我可以不用它。 嗯,“或在运行时做事”不是很精确。如果你在运行时做事,比如在计时器线程中,那么不,你不能没有这些类型的方法。【参考方案2】:Swing is single threaded and all changes to the GUI must be done on EDT
invokeLater()
的基本用法
主要方法应始终包裹在invokeLater()
延迟(但异步)动作/事件到 EventQueue
结束,
如果 EDT 不存在,那么您必须使用 invokeLater()
创建一个新的 EDT。您可以使用if (SwingUtilities.isEventDispatchThread()) ...
进行测试
存在invokeAndWait()
,但直到今天我(只是我的观点)找不到使用invokeAndWait()
而不是invokeLater()
的理由,除了对GUI(JTree 和JTable)的硬更改,但是只需Substance L&F(非常适合测试 EDT 上事件的一致性)
基本资料:Concurrency in Swing
后台任务的所有输出必须包装在invokeLater()
【讨论】:
【参考方案3】:每个 Swing 应用程序至少有 2 个线程:
-
执行应用程序的主线程
EDT(事件调度线程)是一个更新 UI 的线程(因此 UI 不会冻结)。
如果您想更新 UI,您应该在 EDT 中执行代码。 SwingUtilities.invokeLater、SwingUtilities.invokeAndWait、EventQueue.invokeLater、EventQueue.invokeAndWait 等方法允许您通过 EDT 执行代码。
【讨论】:
【参考方案4】:我这次的问题与
SwingUtilities.invokeLater
有关:我应该什么时候使用它?
理解的关键是 Java 有一个单独的线程 (EDT) 处理 Swing 相关事件。
您应该使用invokeLater()
来显示桌面应用程序的主要JFrame
(例如),而不是尝试在当前线程中执行此操作。它还将为以后正常关闭应用程序创建上下文。
对于大多数应用程序来说就是这样。
每次需要更新 GUI 组件时都必须使用吗?它的具体作用是什么?
没有。如果您修改一个 GUI 组件,它将触发一个事件,该事件被注册以供 Swing 稍后调度。如果有此事件的侦听器,EDT 线程将在某个地方调用它。您不需要使用invokeLater()
,只需在组件上正确设置侦听器即可。
请记住,此线程与屏幕上的线程绘图框架等相同。因此,侦听器不应执行复杂/长时间/CPU 密集型任务,否则您的屏幕将冻结。
是否有替代方案,因为它听起来不直观并且添加了看似不必要的代码?
除了在组件上显示您的应用程序和您感兴趣的invokeLater()
+ 侦听器之外,您不需要编写更多代码。其余的由 Swing 处理。
【讨论】:
【参考方案5】:大多数用户启动的事件(点击、键盘)已经在 EDT 上,因此您不必为此使用 SwingUtilities。这涵盖了很多情况,除了你的 main() 线程和更新 EDT 的工作线程。
【讨论】:
好吧,用户可以更新一个正在被更新 GUI 的线程监控的文件。 hmm ... 这不算作(直接,规则所在的位置)用户发起的事件:用户更新文件(在 EDT 上的 Swing 内部)并保存它(通过单击 EDT 上的按钮),触发 OS 文件更新事件(外部摇摆,关闭 EDT)通知,该通知到达负责更新 EDT 上的 GUI 的监视器(关闭 EDT)以上是关于SwingUtilities.invokeLater的主要内容,如果未能解决你的问题,请参考以下文章