SwingUtilities.invokeLater

时间:2011-08-25 20:38:49

标签: java multithreading swing awt event-dispatch-thread

我的问题与SwingUtilities.invokeLater有关。我应该什么时候使用它?每次需要更新GUI组件时是否必须使用?它到底是做什么的?有没有它的替代品,因为它听起来不直观,并添加看似不必要的代码?

5 个答案:

答案 0 :(得分:52)

  

每次需要更新GUI组件时是否必须使用?

不,如果您已经在事件发送线程(EDT)上,那么在响应用户发起的事件(例如点击和选择)时总是如此。 (actionPerformed方法等总是由EDT调用。)

如果您在EDT上但想要进行GUI更新(如果您想从某个计时器线程或某些网络线程等更新GUI),您将拥有安排由EDT执行的更新。这就是这种方法的用途。

Swing基本上是线程不安全的。即,与该API的所有交互都需要在单个线程(EDT)上执行。如果你需要从另一个线程(计时器线程,网络线程......)进行GUI更新,你需要使用你提到的方法(SwingUtilities.invokeLater,SwingUtilities.invokeAndWait,...)。

答案 1 :(得分:14)

Swing is single threaded and all changes to the GUI must be done on EDT 

invokeLater()

的基本用法
  1. 主要方法应始终包含在invokeLater()

  2. 延迟(但异步)操作/事件到EventQueue结尾,

  3. 如果EDT不存在,则必须使用invokeLater()创建新的EDT。您可以使用if (SwingUtilities.isEventDispatchThread()) {...

  4. 进行测试
  5. 存在invokeAndWait(),但直到今天我(仅我的观点)找不到使用invokeAndWait()代替invokeLater()的原因,除了对GUI的硬更改( JTree和JTable),但只有Substance L&F(非常适合测试EDT事件的一致性)

  6. 基本内容:Concurrency in Swing

  7. 后台任务的所有输出必须包含在invokeLater()

答案 2 :(得分:7)

每个Swing应用程序至少有2个线程:

  1. 执行应用程序的主要线程
  2. EDT(事件调度线程)是一个更新UI的线程(因此UI不会冻结)。
  3. 如果要更新UI,则应在EDT中执行代码。 SwingUtilities.invokeLater,SwingUtilities.invokeAndWait,EventQueue.invokeLater,EventQueue.invokeAndWait等方法允许您通过EDT执行代码。

答案 3 :(得分:7)

  

这次我的问题与SwingUtilities.invokeLater有关:我什么时候应该使用它?

要理解的关键是Java有一个单独的线程(EDT)来处理与Swing相关的事件。

您应该使用invokeLater()来显示桌面应用程序的主JFrame(例如),而不是尝试在当前线程中执行此操作。它还将创建上下文,以便稍后正常关闭应用程序。

这适用于大多数应用程序。

  

每次需要更新GUI组件时是否必须使用?它到底是做什么的?

没有。如果修改GUI组件,它将触发一个事件,该事件已注册以供Swing稍后调度。如果有此事件的监听器,EDT线程将在其后的某个地方调用它。您不需要使用invokeLater(),只需在组件上正确设置侦听器即可。

请记住,此线程与您的屏幕上绘制框架等相同。因此,听众不应执行复杂/长/ CPU密集型任务,否则屏幕将冻结。

  

是否有替代品,因为它听起来并不直观,并且添加了看似不必要的代码?

您不需要编写更多代码,而不是使用您对组件感兴趣的invokeLater() +监听器来显示您的应用程序。其余的由Swing处理。

答案 4 :(得分:3)

大多数用户发起的事件(点击,键盘)已经在EDT上,因此您不必使用SwingUtilities。这包括很多情况,除了更新EDT的main()线程和工作线程。