有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java何时使用Swingutiles。invokeAndWait/invokeLater

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

对于基本gui,是否需要使用invokeAndWait在EDT的行中放置类似new SwingGUI().setVisible(true);的内容?只是为了展示

这算吗


共 (4) 个答案

  1. # 1 楼答案

    是的,如果你触摸摇摆物体,你必须在EDT上进行。在大多数情况下,您已经在那里了,但如果没有,请使用SwingUtilities类。原因是Swing类不是多线程的,因此如果在其他线程上访问它,可能会导致严重的问题。这可能是因为setVisible()在封面下做了很多事情来展示一些东西(比如重新布置东西)。最好是安全的

  2. # 2 楼答案

    从你的电话里打过来的任何东西

    public static void main(String[] agrs) {
    

    直接(不生成另一个线程或使用invokeLater)在主线程上运行

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

    如果可以确保EDT不忙(在第一个窗口设置为可见(true)之前),则可以从主线程访问GUI。如果您可以确保EDT没有引用您正在处理的组件(它不在EDT的范围内),即在将其添加到任何容器之前,您可以从主线程访问它,而无需EDT同时访问它,因为EDT无法访问它

  3. # 3 楼答案

    所有访问Swing对象的操作都应该通过事件分派线程(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);
    }
    
  4. # 4 楼答案

    对你的问题的简短回答是:是的,甚至打电话setVisible都应该在EDT上进行。要确定当前线程是否是EDT,可以使用^{}方法

    一些参考链接:

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