何时使用SwingUtilies.invokeAndWait / invokeLater

我在某处看到,对于影响gui视觉效果的任何线程,它应该使用SwingUtilities.invokeAndWait / invokeLater在EDT中运行

对于一个基本的gui,是否需要添加类似new SwingGUI().setVisible(true); 在使用invokeAndWait的EDT中? 只是为了展示?

这算数了吗?

对你的问题的简短回答是:是的,即使调用setVisible应该在EDT上发生。 要确定当前线程是否为EDT,可以使用EventQueue#isDispatchThread方法

一些参考链接:

  • multithreadingSwing应用程序
  • 线程和Swing
  • Swing中的并发性

编辑:在阅读我提供的链接后,似乎Oracle网站上的一些文章已经过时了,因为他们仍然记录您可以在另一个线程上创建Swing组件。 有一个stackoverflow问题 ,其中包含一些很好的答案和链接到博客文章和有关“新”政策的文章(几年前的新政策)

是的,如果您触摸Swing对象,则必须在EDT上执行此操作。 在大多数情况下,您已经在那里,但如果没有,请使用SwingUtilities类。 原因是Swing类不是multithreading的,因此如果您在其他线程上访问它,可能会导致令人讨厌的问题。 并且可能是setVisible()在掩盖下做了很多事情来制作一些东西(比如重新铺设东西)。 更安全。

任何来自你的东西

 public static void main(String[] agrs) { 

直接(没有产生另一个线程或使用invokeLater)正在主线程上运行。

在EDT(由用户输入触发)访问(同时)访问GUI主对象时,可以使用主线程访问GUI对象,这可能导致线程问题。 调用invokeLater会导致任务(runnables)在EDT上运行,从而阻止其他EDT任务同时访问,即。 按钮按等

如果您可以确定EDT不忙(在第一个窗口是setVisible(true)之前),您可以从主线程访问GUI。 如果您可以确定EDT没有参考您正在处理的组件(它超出了EDT的范围),即。 在将它添加到任何容器之前,您可以从主线程访问它,而EDT无法同时访问它,因为EDT无法访问它。

访问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); }