更新edt中的swing组件 [英] Updating swing components within edt

查看:115
本文介绍了更新edt中的swing组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If I understand correctly then when I create GUI swing components, for example I have this:

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

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

So as long as I don't call the setVisible method the components are being made from the thread the instance was created. So if in a class where i have my main method write:

JFrame test=new frameExample();

我sysout

Thread.currentThread.getName(); 

在frameVisible中的frameExample中的构造函数中,我应该得到:main.

in the constructor in frameExample just before setVisible I should get: main.

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

After that the responsibility of creating and maintaining swing elements are passed to the event-dispatch-thread and because it is not thread safe every component add/remove/modify should be done within the EDT thread.

所以我应该将setVisible放置在构造函数中的最后一行代码中,或者单独调用它.

So I should place my setVisible as the last line of code in my constructor, or call it separately.

据我了解,所有事件监听都是通过EDT进行的.因此,如果我在一个actionPerformed方法中创建一个新组件,它将很好.

As I understand all event listening goes through the EDT. So if I create a new component within for example an actionPerformed method it should do fine.

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

Also if I pass a runnable instance to invokeLater or invokeAndWait then all the run() method will be done by the EDT.

这就是我感到困惑的原因.

So here is why I'm confused.

我编写了以下代码:

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更新其组件?这个?).

So in my anonim class where I add the two buttons im in the EDT, but the components are not added to my frame just after i resize it (which forces the edt to update its components??? what is the reason for this?).

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

So i dont get my new components even within edt, however when i create a random thread outside edt and make it change some gui element property (for example setText) in just works fine outside the edt.

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

So my first question is: why my components are not updated within edt and why they are visible after resize

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

second one: why can i make changes to swing components outside edt and everything works fine? Is this just random thread behvior where for example things just work fine without sync block but when you rerun you program at some point it will eventually crash because the lack of sync.

推荐答案

只要我不调用setVisible方法,组件都是从创建实例的线程中制成的

So as long as I don't call the setVisible method the components are being made from the thread the instance was created

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

Wrong. As long as you do not specifically create a new Thread or use a utility method (like for example the SwingUtilities#invoke... methods), each call is invoked on the current Thread, including the setVisible call.

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

It looks like you think that making Swing components visible somehow makes your code switch threads. No, the painting of the Swing components will happen on the EDT. And as you correctly stated, Swing is not thread safe. That is why you should create the component on the EDT as well, and not on another thread. It might work without problems the majority of the time, but eventually you will stumble upon weird bugs.

据我了解,所有事件监听都是通过EDT进行的.因此,如果我在一个actionPerformed方法中创建一个新组件,它将很好.

As I understand all event listening goes through the EDT. So if I create a new component within for example an actionPerformed method it should do fine.

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

Also if I pass a runnable instance to invokeLater or invokeAndWait then all the run() method will be done by the EDT.

正确.

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

So in my anonim class where I add the two buttons im in the EDT, but the components are not added to my frame just after i resize it

Container中添加组件要求您重新验证布局(请参见Container#add方法的javadoc).只需致电

Adding components to a Container requires you to revalidate the layout (see the javadoc of the Container#add method). Just call

revalidate();
repaint();

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

after you add the buttons and it will work as expected. Manually resizing the frame has the same effect as you already noticed.

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

So i dont get my new components even within edt, however when i create a random thread outside edt and make it change some gui element property (for example setText) in just works fine outside the edt.

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

As stated before, it might work most of the time, but there is no guarantee it will work 100% of the time. The reason the adding of your components did not work as expected is explained above, and has nothing to do with threading issues.

这篇关于更新edt中的swing组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆