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个线程:

  1. 执行应用程序的主线程
  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()线程和工作线程。