SwingUtilities.invokeLater
我的问题是关于SwingUtilities.invokeLater
。 我应该什么时候使用它? 每次我需要更新GUI组件时,是否必须使用? 它究竟做了什么? 有没有其他的选择,因为它听起来不直观,并增加了看似不必要的代码?
每次我需要更新GUI组件时,是否必须使用?
不,如果您已经在事件调度线程(EDT)上,那么响应用户发起的事件(例如点击和选择)时总是如此。 ( actionPerformed
方法等,总是由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()
1)主要的方法应该总是包装到invokeLater()
2)延迟(但异步)动作/事件到EventQueue
的结尾,
3)如果EDT不存在,则必须使用invokeLater()
创建一个新的EDT
你可以测试它与if (SwingUtilities.isEventDispatchThread()) {...
4)存在invokeAndWait()
,但直到今天我( just my view
)不能找到使用invokeAndWait()
而不是invokeLater()
,除了到GUI(JTree&JTable)的硬改变,但物质L&F非常适合测试EDT上事件的一致性)
5) 基本的东西
6)所有来自BackGround Tasks的输出必须被包装到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()线程和工作线程。