【发布时间】:2014-04-25 21:15:08
【问题描述】:
对于 Swing 应用程序,我们使用EventQueue.invokeLater() 有什么原因吗? Thread.start() 不应该以同样的方式工作吗?
Thread.start 的另一个优点是我们可以告诉线程中断,因为EventQueue.invokeLater 没有为我们提供Thread 对象。
【问题讨论】:
标签: java multithreading swing
对于 Swing 应用程序,我们使用EventQueue.invokeLater() 有什么原因吗? Thread.start() 不应该以同样的方式工作吗?
Thread.start 的另一个优点是我们可以告诉线程中断,因为EventQueue.invokeLater 没有为我们提供Thread 对象。
【问题讨论】:
标签: java multithreading swing
您应该使用 EventQueue.invokeLater 进行所有 GUI 更新,因为 Swing 在某种程度上是单线程的。见http://docs.oracle.com/javase/6/docs/api/javax/swing/package-summary.html#threading
您可以启动线程进行计算等,但应使用 invokeLater 更新 GUI。
【讨论】:
So if you're not doing any GUI update, but doing "model" update is it fine to use Thread.start - 不,因为对模型的更改会导致 GUI 组件重新绘制自身。
启动 Swing 应用程序的两个选项是:
EventQueue.invokeLater()
和
SwingUtilities.invokeLater()
我的偏好是使用 SwingUtilities。他们都将可运行文件放在Event Dispatch thread (EDT) 上。您不需要 EDT 的句柄。
您的代码要么在 EDT 上,要么另一个调用 invokeLater() 方法会将可运行对象放在 EDT 上。您可以使用 SwingUtilities.isEventDispatchThread() 方法调用来确定任一条件。
Thread.start() 方法适用于您自己的工作线程。或者,如果您愿意,可以将 javax.swing.SwingWorker 类用于您自己的 Swing 工作线程。
这是我用来启动我编写的每个 Swing 应用程序的样板。
package com.ggl.game2048;
import javax.swing.SwingUtilities;
import com.ggl.game2048.model.Game2048Model;
import com.ggl.game2048.view.Game2048Frame;
public class Game2048 implements Runnable {
@Override
public void run() {
new Game2048Frame(new Game2048Model());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Game2048());
}
}
简明扼要。这个类做了 3 件事。
您可以在我的 Java 文章中查看 2048 Swing application 的其余部分。
【讨论】:
SwingUtilities.invokeLater(…) 只是委托给EventQueue.invokeLater(…)。看不到您喜欢使用SwingUtilities 的备份...顺便说一下,您可以不将javax.swing.Timer 类用于您的“自己的Swing 工作线程”。 Swing 的 Timer 只是在 EDT 内传递 ActionEvents。