简体   繁体   English

SwingUtilities.invokeLater

[英]SwingUtilities.invokeLater

My question is related to SwingUtilities.invokeLater . 我的问题与SwingUtilities.invokeLater有关。 When should I use it? 我什么时候应该使用它? Do I have to use each time I need to update the GUI components? 每次需要更新GUI组件时都需要使用吗? What does it exactly do? 它到底是做什么的? Is there an alternative to it since it doesn't sound intuitive and adds seemingly unnecessary code? 因为听起来不直观并且添加了看似不必要的代码,所以还有其他替代方法吗?

Do I have to use each time I need to update the GUI components? 每次需要更新GUI组件时都需要使用吗?

No, not if you're already on the event dispatch thread (EDT) which is always the case when responding to user initiated events such as clicks and selections. 不,如果您已经在事件分配线程(EDT)上,则不是这样,在响应用户发起的事件(例如单击和选择)时,总是这样。 (The actionPerformed methods etc, are always called by the EDT.) actionPerformed方法等始终由EDT调用。)

If you're not on the EDT however and want to do GUI updates (if you want to update the GUI from some timer thread, or from some network thread etc), you'll have to schedule the update to be performed by the EDT. 但是,如果您不在 EDT上并且想要进行GUI更新(如果您想从某个计时器线程或某个网络线程等更新GUI),则必须安排要由EDT执行的更新。 That's what this method is for. 这就是这种方法的目的。

Swing is basically thread unsafe. 摆动基本上是线程不安全的。 Ie, all interaction with that API needs to be performed on a single thread (the EDT). 即,与该API的所有交互都需要在单个线程(EDT)上执行。 If you need to do GUI updates from another thread (timer thread, networking thread, ...) you need to use methods such as the one you mentioned (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...). 如果需要从另一个线程(计时器线程,网络线程等)进行GUI更新,则需要使用您提到的方法(SwingUtilities.invokeLater,SwingUtilities.invokeAndWait等)。

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

Basic usage for invokeLater() invokeLater()基本用法

  1. Main methods should be always wrapped in invokeLater() 主要方法应始终包装在invokeLater()

  2. Delayed (but asynchronously) action/event to the end of EventQueue , 将动作/事件延迟(但异步)到EventQueue的末尾,

  3. If EDT doesn't exists then you have to create a new EDT by using invokeLater() . 如果EDT不存在,则必须使用invokeLater()创建一个新的EDT。 You can test it with if (SwingUtilities.isEventDispatchThread()) {... 您可以使用if (SwingUtilities.isEventDispatchThread()) {...

  4. There exists invokeAndWait() , but till today I (just my view) can't find a reason for using invokeAndWait() instead of invokeLater() , except hard changes into GUI (JTree & JTable), but just with Substance L&F (excellent for testing consistency of events on the EDT) 存在invokeAndWait() ,但是直到今天,我(只是我的观点)仍然找不到使用invokeAndWait()而不是invokeLater()的理由,除了对GUI(JTree和JTable)进行的硬更改外,仅使用Substance L&F (非常好)用于在EDT上测试事件的一致性)

  5. Basic stuff: Concurrency in Swing 基本内容: Swing中的并发

  6. All output from background tasks must be wrapped in invokeLater() 后台任务的所有输出必须包装在invokeLater()

Every Swing application has at least 2 threads: 每个Swing应用程序至少具有2个线程:

  1. The main thread that executes the application 执行应用程序的主线程
  2. The EDT (Event Dispatching Thread) is a thread that updates the UI (so the UI will not freeze). EDT(事件调度线程)是用于更新UI的线程(因此UI不会冻结)。

If you want to update the UI you should execute code within the EDT. 如果要更新UI,则应在EDT中执行代码。 Methods like SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait allow you to execute code by the EDT. 诸如SwingUtilities.invokeLater,SwingUtilities.invokeAndWait,EventQueue.invokeLater,EventQueue.invokeAndWait之类的方法允许您通过EDT执行代码。

My question this time is related to SwingUtilities.invokeLater : When should I use it? 我这次的问题与SwingUtilities.invokeLater有关:什么时候应该使用它?

What is key to understand is that Java has a separate thread (EDT) handling Swing related events. 要理解的关键是Java具有一个单独的线程(EDT)处理Swing相关事件。

You should use invokeLater() to display the main JFrame of a desktop application (for example), instead of trying to do it in the current thread. 您应该使用invokeLater()来显示桌面应用程序的主JFrame (例如),而不是尝试在当前线程中执行此操作。 It will also create the context for graceful closing of the application later. 它还将创建上下文,以供以后正常关闭应用程序。

That's about it for most applications. 多数应用程序就是这样。

Do I have to use each time I need to update the GUI components? 每次需要更新GUI组件时都需要使用吗? What does it exactly do? 它到底是做什么的?

No. If you modify a GUI component, it will trigger an event which is registered for later dispatching by Swing. 否。如果您修改GUI组件,它将触发一个事件,该事件已注册,以后由Swing调度。 If there is a listener for this event, the EDT thread will call it somewhere down the road. 如果有此事件的侦听器,则EDT线程将在以后的某个地方调用它。 You don't need to use invokeLater() , just set your listeners on components properly. 您不需要使用invokeLater() ,只需在组件上正确设置侦听器即可。

Keep in mind that this thread is the same thread drawing frames etc... on your screen. 请记住,该线程与屏幕上的线程绘制框架等相同。 Hence, listeners should not perform complex/long/CPU intensive tasks, otherwise your screen will freeze. 因此,侦听器不应执行复杂/长时间/占用大量CPU的任务,否则屏幕将冻结。

Is there an alternative to it since it doesn't sound intuitive and adds seemingly unnecessary code? 因为听起来不直观并且添加了看似不必要的代码,所以还有其他替代方法吗?

You don't need to write more code than displaying your application with invokeLater() + listeners you are interested in on component. 除了使用您对组件感兴趣的invokeLater() +侦听器显示应用程序外,您不需要编写更多的代码。 The rest is handled by Swing. 其余的由Swing处理。

Most user-initiated events (clicks, keyboard) will already be on the EDT so you won't have to use SwingUtilities for that. 大多数用户启动的事件(单击,键盘)已经在EDT上,因此您不必为此使用SwingUtilities。 That covers a lot of cases, except for your main() thread and worker threads that update the EDT. 除了您的main()线程和更新EDT的辅助线程之外,这涉及很多情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM