我非常好奇为什么我们必须使用java.awt.EventQueue.invokeLater
来控制swing组件。
为什么我们不能在普通线程中这样做呢?幕后到底发生了什么?据我所知,如果我有一个JFrame
,我可以在主线程中将可见性设置为true或false,而不会收到任何错误,而且它似乎确实起作用了。那么,我通过使用java.awt.EventQueue.invokeLater
到底能实现什么呢?我也充分意识到我可以使用SwingUtilities.invokeLater
,但作为explained here,它们似乎是一回事。
感谢任何人的解释。希望这是一个有效的问题。
编辑:要回答wumpz问题,我们可以创建jframe
JFrame frame = new JFrame("Hello world");
frame.setSize(new Dimension(300, 300));
frame.setPreferredSize(new Dimension(300, 300));
frame.setMaximumSize(new Dimension(300, 300));
frame.setMinimumSize(new Dimension(300, 300));
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
并在创建它的同一线程上执行以下操作。
for (int i = 0; i < 34; i++)
{
System.out.println("Main thread setting to "+(!frame.isVisible()));
frame.setVisible(!frame.isVisible());
}
也没有什么抱怨。
发布于 2014-03-20 21:45:46
完整的Swing处理是在一个称为EDT (事件分派线程)的线程中完成的。因此,如果您要在此线程中计算一些持续时间较长的计算,则会阻塞GUI。
这里的方法是在不同的线程中处理您的计算,以便您的GUI保持响应。最后,你想要更新你的图形用户界面,这是必须在EDT中完成的。现在EventQueue.invokeLater
开始发挥作用了。它会在Swings事件列表的末尾发布一个事件(您的Runnable
),并在处理完之前的所有图形用户界面事件后进行处理。
这里也可以使用EventQueue.invokeAndWait
。不同之处在于,在GUI更新之前,计算线程会阻塞。所以很明显,这不能在EDT中使用。
从不同的线程更新Swing图形用户界面时要小心,不要使用。在大多数情况下,这会产生一些奇怪的更新/刷新问题。
仍然有一些Java代码可以从主线程启动一个简单的JFrame。这可能会导致问题,但不会阻止Swing。大多数现代的IDE现在都会创建类似这样的东西来启动GUI:
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
发布于 2014-03-20 21:39:02
所有supported platforms都提供单线程图形库。Swing是跨平台的。因此,只能在event dispatch thread上构造和操作Swing GUI对象。
顺便说一句,从1.3版开始,SwingUtilities.invokeLater()
就是EventQueue.invokeLater()
的封面。
https://stackoverflow.com/questions/22534356
复制相似问题