我在某地读到,对于影响gui视觉效果的任何线程,它应该使用SwingUtilities.invokeAndWait / invokeLater在EDT中运行
对于基本的gui,是否有必要使用invokeAndWait将new SwingGUI().setVisible(true);
之类的东西放在EDT的行中?只是为了显示?
这算得上吗?
答案 0 :(得分:9)
对你的问题的简短回答是:是的,甚至在美国东部时间调用setVisible
也是如此。要确定当前线程是否为EDT,您可以使用EventQueue#isDispatchThread
方法
一些参考链接:
编辑: 在阅读了我提供的链接后,似乎Oracle网站上的一些文章已经过时了,因为他们仍然可以在另一个线程上创建Swing组件。这里有一个stackoverflow question,其中包含一些很好的答案以及博客文章和关于“新”政策的文章的链接(几年前的新内容)
答案 1 :(得分:3)
是的,如果您触摸Swing对象,则必须在EDT上执行此操作。在大多数情况下,您已经在那里,但如果没有,请使用SwingUtilities
类。原因是Swing类不是多线程的,因此如果您在其他线程上访问它,可能会导致令人讨厌的问题。而且setVisible()
可能会在幕后做很多事情来制作一些东西(比如重新铺设东西)。更安全。
答案 2 :(得分:0)
从您的
调用的任何内容public static void main(String[] agrs) {
直接(没有产生另一个线程或使用invokeLater)正在主线程上运行。
在EDT(由用户输入触发)访问(同时)访问GUI主对象时,可能会导致线程问题。调用invokeLater会导致任务(runnables)在EDT上运行,从而阻止其他EDT任务同时访问,即。按钮按等。
如果可以确定EDT不忙(在第一个窗口设置为可见(真)之前),则可以从主线程访问GUI。如果您可以确定EDT没有参考您正在处理的组件(它超出了EDT的范围),即。在将其添加到任何容器之前,您可以从主线程访问它而EDT无法同时访问它,因为EDT无法访问它。
答案 3 :(得分:-1)
访问Swing对象的所有内容都应该通过Event Dispatch Thread(EDT)来实现。这有一个小例外(我将在后面提到)。 EDT的目的是处理由于IO(鼠标和键盘事件)而可能发生的任何事件。很多时候这可能意味着改变GUI的布局。 Swing没有开发为线程安全的,这意味着如果两个线程试图同时修改同一个组件,那么最终可能会出现损坏的GUI。由于已经有一个已知的线程要访问Swing组件(EDT),因此没有其他线程可以尝试修改它们甚至读取它们的状态。
现在,在特殊情况下,您可以在EDT之外操作Swing对象。在任何组件变得可见之前,IO不可能触发事件。因此,主线程可以设置Swing GUI,然后将单个JFrame设置为可见。由于现在可以发生可见的帧IO事件,并且主线程不应该尝试修改任何更多的Swing组件。应该只使用这个选项来启动GUI,实际上只有玩具问题。
我所说的是以下情况很好,如果你只是玩弄东西,不会引起问题。
public static void main(String[] args) {
// create components
JFrame f = new JFrame();
...
// do layout and other bits of setup
// show gui to user
f.setVisible(true);
}