繁体   English   中英

更新edt中的swing组件

[英]Updating swing components within edt

如果我理解正确,那么在创建GUI swing组件时,例如,我有以下内容:

public class frameExample extends JFrame{
    public frameExample(){
    //Here adding bunch if components
    setVisible(true);
    }
}

因此,只要我不调用setVisible方法,就可以从创建实例的线程中创建组件。 因此,如果在我有我的主要方法的课堂上写:

JFrame test=new frameExample();

而我系统

Thread.currentThread.getName(); 

在setVisible之前的frameExample中的构造函数中,我应该得到:main。

此后,创建和维护swing元素的责任被传递给event-dispatch-thread,并且由于它不是线程安全的,因此每个组件的添加/删除/修改都应在EDT线程内完成。

因此,我应该将setVisible放置为构造函数中的最后一行代码,或单独调用它。

据我了解,所有事件监听都是通过EDT进行的。 因此,如果我在一个actionPerformed方法中创建一个新组件,它应该可以正常工作。

同样,如果我将可运行实例传递给invokeLater或invokeAndWait,则所有run()方法都将由EDT完成。

所以这就是为什么我感到困惑的原因。

我做了这段代码:

public class GUI extends JFrame {


JButton btn = new JButton("Change");
JMenuBar m = new JMenuBar();

public GUI() {
    super("Test");
    setSize(400, 400);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    m.add(new JMenu("menu"));
    add(m, BorderLayout.NORTH);

    add(btn, BorderLayout.SOUTH);
    System.out.println("Current thread: before setVisible "+Thread.currentThread().getName());

    setVisible(true);

    System.out.println("Current thread: after setVisible "+Thread.currentThread().getName());
    btn.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            add(new JButton("testbtn1"), BorderLayout.EAST);
            add(new JButton("testbtn2"));
            System.out.println("Current thread: "+Thread.currentThread().getName());


            new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for (int i = 0; i < 1E8; i++) {
                        Math.sin(5.0);
                    }
                    System.out.println("Current thread: "+Thread.currentThread().getName());
                }
            }).start();

        }
    });
}

}

因此,在我的anonim类中,我在EDT中添加了两个按钮im,但是在我调整其大小后才将组件添加到我的框架中(这迫使edt更新其组件?这是什么原因?) 。

所以我什至没有在edt中获得我的新组件,但是当我在edt之外创建一个随机线程并使其更改某些gui元素属性(例如setText)时,在edt之外也可以正常工作。

所以我的第一个问题是:为什么我的组件未在edt中更新,以及为什么它们在调整大小后可见

第二个:为什么我可以更改edt之外的摆动组件,并且一切正常? 这是否只是随机线程,例如在没有同步块的情况下一切正常,但是当您重新运行程序时,由于缺少同步,它最终会崩溃。

因此,只要我不调用setVisible方法,就可以从创建实例的线程中创建组件

错误。 只要您没有专门创建新的Thread或使用实用程序方法(例如SwingUtilities#invoke...方法),每个调用都会在当前Thread上调用,包括setVisible调用。

好像您认为使Swing组件可见一样会使代码切换线程成为可能。 不,Swing组件的绘制将在EDT上进行。 正如您正确指出的那样,Swing不是线程安全的。 这就是为什么您也应该在EDT上而不是在另一个线程上创建组件的原因。 在大多数情况下,它可能没有问题,但是最终您会发现奇怪的错误。

据我了解,所有事件监听都是通过EDT进行的。 因此,如果我在一个actionPerformed方法中创建一个新组件,它应该可以正常工作。

同样,如果我将可运行实例传递给invokeLater或invokeAndWait,则所有run()方法都将由EDT完成。

正确。

因此,在我的anonim类中,我在EDT中添加了两个按钮im,但是在我调整其大小之后,组件并没有添加到我的框架中

Container添加组件需要您重新验证布局(请参见Container#add方法的javadoc)。 刚打电话

revalidate();
repaint();

添加按钮后,它将按预期工作。 手动调整框架的大小与您已经注意到的效果相同。

所以我什至没有在edt中获得我的新组件,但是当我在edt之外创建一个随机线程并使其更改某些gui元素属性(例如setText)时,在edt之外也可以正常工作。

如前所述,它可能在大多数时间都可以工作,但是不能保证它将在100%的时间内工作。 上面已说明了添加组件无法按预期方式工作的原因,并且与线程问题无关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM