Java SwingUtilities.invokeLater() 为什么需要它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3551542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SwingUtilities.invokeLater() why is it needed?
提问by pure.java
Why is it necessary to put GUI update code in SwingUtilities.invokeLater()
?
为什么需要将GUI更新代码放入SwingUtilities.invokeLater()
?
Why cant it be internally taken care of by Swing itself? Why does the caller have to care about how swing handles UI updates?
为什么它不能由 Swing 本身在内部处理?为什么调用者必须关心swing 如何处理UI 更新?
采纳答案by Richard Fearn
Swing objects are not thread safe. SwingUtilities.invokeLater()
allows a task to be executed at some later point in time, as the name suggests; but more importantly, the task will be executed on the AWT event dispatch thread. When using invokeLater
, the task is executed asynchronously; there's also invokeAndWait
, which won't return until the task has finished executing.
Swing 对象不是线程安全的。SwingUtilities.invokeLater()
顾名思义,允许在稍后的某个时间点执行任务;但更重要的是,任务将在 AWT 事件调度线程上执行。使用时invokeLater
,任务异步执行;还有invokeAndWait
,在任务执行完成之前不会返回。
Some information about the decision not to make Swing thread-safe can be found here: Multithreaded toolkits: A failed dream?
关于不使 Swing 线程安全的决定的一些信息可以在这里找到:多线程工具包:一个失败的梦想?
回答by Paul Tomblin
Because GUI updates must be done in the event dispatch thread. If you're operating in a different thread, doing the update in invokeLater
yanks it out of your thread and into the event thread.
因为 GUI 更新必须在事件调度线程中完成。如果您在不同的线程中操作,则执行更新invokeLater
会将其从您的线程中拉出并进入事件线程。
More explanation here: http://www.oracle.com/technetwork/java/painting-140037.html
更多解释在这里:http: //www.oracle.com/technetwork/java/painting-140037.html
The smart thing to do with big updates (like repopulating a JTable from the database) on Swing is to get the underlying model, do the updates on the model in your thread, then fire off a notification using invokeLater
. That keeps your gui responding to events and redrawing. If the update is going to be very extensive, you can even fire off these notifications with invokeLater
at regular intervals while you're updating, like every second or two.
在 Swing 上进行大更新(例如从数据库重新填充 JTable)的明智之举是获取底层模型,在线程中对模型进行更新,然后使用invokeLater
. 这使您的 gui 可以响应事件和重绘。如果更新将非常广泛,您甚至invokeLater
可以在更新时定期发出这些通知,例如每隔一两秒。
回答by Colin Hebert
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI.
...
导致 doRun.run() 在 AWT 事件调度线程上异步执行。这将在处理完所有待处理的 AWT 事件后发生。当应用程序线程需要更新 GUI 时,应使用此方法。
...
回答by Joey
Swing is single-threaded. Every update to the UI musthappen from the so-called EDT – the event-dispather thread which is the main GUI thread Swing (and I think AWT) uses. If you don't do this, then weird things can or will happen (though I like Windows Forms better here which just throws an exception if you do it wrong).
Swing 是单线程的。UI 的每次更新都必须从所谓的 EDT 发生——事件分发器线程是 Swing(我认为是 AWT)使用的主 GUI 线程。如果你不这样做,那么奇怪的事情可能或将会发生(尽管我更喜欢 Windows 窗体,如果你做错了它只会抛出一个异常)。
That being said, you don't need to wrap every single UI operation into SwingUtilities.invokeLater()
– if the code you're writing is already executed by the EDT this isn't needed. So the ActionListener
for a button click doesn't need this. But a listener on an external object, running in some other thread, that updates a JLabel
somewhere – there you need it.
话虽如此,您不需要将每个 UI 操作都包装到其中SwingUtilities.invokeLater()
——如果您编写的代码已经由 EDT 执行,则不需要。所以ActionListener
for a button click 不需要这个。但是外部对象上的侦听器,在其他线程中运行,更新JLabel
某个地方——你需要它。
回答by Mark
Swing was not written to be a thread safe GUI toolkit so all GUI updates should happen from a single thread to avoid any deadlocks. In Swing this is the Event Dispatcher Thread (EDT).
Swing 不是为了成为线程安全的 GUI 工具包而编写的,因此所有 GUI 更新都应该在单个线程中进行,以避免出现任何死锁。在 Swing 中,这是事件调度程序线程 (EDT)。
See Concurrent in Swingfrom the Java tutorial for more details. It also references thisblog entry on why it is hard to write a multithreaded GUI toolkit.
有关更多详细信息,请参阅Java 教程中的 Swing 中的并发。它还引用了这篇关于为什么很难编写多线程 GUI 工具包的博客条目。
回答by OscarRyz
All the painting of the components should be performed in a single thread, so, they are rendered properly. That way the component will know, what part has already been painted and which part hasn't.
组件的所有绘制都应在单个线程中执行,因此它们可以正确渲染。这样组件就会知道,哪些部分已经绘制,哪些部分还没有绘制。
If you invoke a "painting" related method ( paint, update, paintComponent, show, setVisible, pack etc. ) outside the EDT, you'll be trying to paint in two different threads, and that may bring problems.
如果您在 EDT 之外调用与“绘画”相关的方法(paint、update、paintComponent、show、setVisible、pack 等),您将尝试在两个不同的线程中绘画,这可能会带来问题。
When you need to use another thread to update the UI, you should invoke it with the invokeLater facility, which in turn will put it in the EDT for you, so you still paint in the same thread.
当您需要使用另一个线程来更新 UI 时,您应该使用 invokeLater 工具调用它,该工具反过来会将它放入 EDT 中,因此您仍然在同一个线程中绘制。
You don't need to use it, if you're coding in a method that runs in the EDT already ( for instance, actionPerformed
or paint
or one of those ) Or if you are executing code not UI related ( for instance, processing files in the background etc. )
你并不需要使用它,如果你在一个方法的编码,在美国东部时间已经运行(例如,actionPerformed
或paint
或其中之一),或者如果您正在执行的代码没有相关的用户界面(例如,在处理文件背景等)
To better understand all these concepts read:The single thread rule
为了更好地理解所有这些概念,请阅读:单线程规则
回答by helios
Repeating others:Swing is not thread safe so one thread must do all the updates to avoid concurrency problems. invokeLater is an utility method to execute something inside the event processing thread.
重复其他:Swing 不是线程安全的,因此一个线程必须完成所有更新以避免并发问题。invokeLater 是一种实用方法,用于在事件处理线程内执行某些操作。
Why doesn't Swing does it internally:this is my impression... I think because it would be overkill -to check every place where an update is taking place. It would bloat the Swing code, dificult the review and maintainability of the code.
为什么 Swing 不在内部执行此操作:这是我的印象……我认为因为检查每个发生更新的地方都太过分了。它会使 Swing 代码膨胀,使代码的和可维护性变得困难。
By the other hand it's not that dificult for an application to know if it's not executing inside the GUI thread and call invokeLater. It will be when the own application launched some thread before.
另一方面,应用程序知道它是否不在 GUI 线程内执行并调用 invokeLater 并不难。它将是在自己的应用程序之前启动某个线程时。