为什么需要将GUI更新代码放入SwingUtilities.invokeLater()
?
为什么它不能被Swing本身内部照顾?为什么调用者必须关心swing如何处理UI更新?
Ric*_*arn 41
Swing对象不是线程安全的.SwingUtilities.invokeLater()
允许任务在稍后的某个时间点执行,顾名思义; 但更重要的是,该任务将在AWT事件派发线程上执行.使用时invokeLater
,任务以异步方式执行; 还有invokeAndWait
,在任务完成执行之前不会返回.
关于决定不使Swing线程安全的一些信息可以在这里找到:多线程工具包:一个失败的梦想?
Pau*_*lin 16
因为GUI更新必须在事件派发线程中完成.如果你在另一个线程中运行,那么在你的线程中进行更新invokeLater
并进入事件线程.
更多解释如下:http://www.oracle.com/technetwork/java/painting-140037.html
在Swing上进行大更新(比如从数据库重新填充JTable)的聪明之处是获取底层模型,在线程中对模型进行更新,然后使用激活通知invokeLater
.这可以让你的gui响应事件和重绘.如果更新非常广泛,您甚至invokeLater
可以在更新时定期触发这些通知,例如每隔一两秒.
Swing是单线程的.UI的每次更新都必须来自所谓的EDT - 事件 - 调度线程,它是Swing(我认为AWT)使用的主要GUI线程.如果你不这样做,那么可能会或将要发生奇怪的事情(虽然我更喜欢Windows FOrms,如果你做错了就会抛出异常).
话虽这么说,你不需要将每个UI操作包装成SwingUtilities.invokeLater()
- 如果你正在编写的代码已经由EDT执行,则不需要.所以ActionListener
点击按钮不需要这个.但是一个外部对象的监听器,在其他一些线程中运行,在JLabel
某个地方更新- 你需要它.
Swing没有被编写为线程安全的GUI工具包,因此所有GUI更新都应该从单个线程发生,以避免任何死锁.在Swing中,这是事件调度程序线程(EDT).
有关更多详细信息,请参阅Java教程中的Swurrent中的Concurrent.它还引用了这篇博客文章,说明为什么编写多线程GUI工具包很困难.