我的问题与SwingUtilities.invokeLater
有关。我应该什么时候使用它?每次需要更新GUI组件时是否必须使用?它到底是做什么的?有没有它的替代品,因为它听起来不直观,并添加看似不必要的代码?
答案 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()
主要方法应始终包含在invokeLater()
延迟(但异步)操作/事件到EventQueue
结尾,
如果EDT不存在,则必须使用invokeLater()
创建新的EDT。您可以使用if (SwingUtilities.isEventDispatchThread()) {...
存在invokeAndWait()
,但直到今天我(仅我的观点)找不到使用invokeAndWait()
代替invokeLater()
的原因,除了对GUI的硬更改( JTree和JTable),但只有Substance L&F(非常适合测试EDT事件的一致性)
基本内容:Concurrency in Swing
后台任务的所有输出必须包含在invokeLater()
答案 2 :(得分:7)
每个Swing应用程序至少有2个线程:
如果要更新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()线程和工作线程。