我的问题与SwingUtilities.invokeLater
. 我应该什么时候使用它?每次需要更新 GUI 组件时都必须使用吗?它究竟是做什么的?是否有替代方案,因为它听起来不直观并且添加了看似不必要的代码?
5 回答
每次需要更新 GUI 组件时都必须使用吗?
不,如果您已经在事件调度线程 (EDT) 上,则不会,这在响应用户发起的事件(例如点击和选择)时总是如此。(actionPerformed
方法等总是由 EDT 调用。)
但是,如果您不在EDT 上并且想要进行 GUI 更新(如果您想从某个计时器线程或某个网络线程等更新 GUI),您必须安排由 EDT 执行更新. 这就是这个方法的用途。
Swing 基本上是线程不安全的。即,与该 API 的所有交互都需要在单个线程(EDT)上执行。如果您需要从另一个线程(计时器线程、网络线程...)进行 GUI 更新,您需要使用您提到的方法(SwingUtilities.invokeLater、SwingUtilities.invokeAndWait...)。
Swing is single threaded and all changes to the GUI must be done on EDT
基本用法invokeLater()
主要方法应始终包含在
invokeLater()
延迟(但异步)动作/事件到结束
EventQueue
,如果 EDT 不存在,那么您必须使用
invokeLater()
. 你可以用if (SwingUtilities.isEventDispatchThread()) {...
存在
invokeAndWait()
,但直到今天我(只是我的观点)找不到使用invokeAndWait()
代替的理由invokeLater()
,除了对 GUI(JTree 和 JTable)的硬更改,但只是使用Substance L&F(非常适合测试 EDT 上事件的一致性)基础知识:Swing 中的并发
后台任务的所有输出都必须包含在
invokeLater()
每个 Swing 应用程序至少有 2 个线程:
- 执行应用程序的主线程
- EDT(事件调度线程)是一个更新 UI 的线程(因此 UI 不会冻结)。
如果你想更新 UI,你应该在 EDT 中执行代码。SwingUtilities.invokeLater、SwingUtilities.invokeAndWait、EventQueue.invokeLater、EventQueue.invokeAndWait 等方法允许您通过 EDT 执行代码。
我这次的问题是
SwingUtilities.invokeLater
:我应该什么时候使用它?
理解的关键是 Java 有一个单独的线程 (EDT) 来处理与 Swing 相关的事件。
您应该使用invokeLater()
来显示JFrame
桌面应用程序的主要内容(例如),而不是尝试在当前线程中执行此操作。它还将为以后正常关闭应用程序创建上下文。
大多数应用程序就是这样。
每次需要更新 GUI 组件时都必须使用吗?它究竟是做什么的?
不可以。如果您修改 GUI 组件,它将触发一个事件,该事件会被注册以供 Swing 稍后调度。如果有此事件的侦听器,EDT 线程将在某个地方调用它。您不需要使用invokeLater()
,只需在组件上正确设置侦听器即可。
请记住,此线程与屏幕上的线程绘图框架等相同。因此,侦听器不应执行复杂/长时间/CPU 密集型任务,否则您的屏幕将冻结。
是否有替代方案,因为它听起来不直观并且添加了看似不必要的代码?
invokeLater()
除了在组件上使用您感兴趣的 + 侦听器显示您的应用程序之外,您不需要编写更多代码。其余的由 Swing 处理。
大多数用户发起的事件(点击、键盘)已经在 EDT 上,因此您不必为此使用 SwingUtilities。这涵盖了很多情况,除了更新 EDT 的 main() 线程和工作线程。