【发布时间】:2015-04-23 04:47:09
【问题描述】:
如果我理解正确,那么当我创建 GUI 摆动组件时,例如我有这个:
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();
}
});
}
}
所以在我的匿名类中,我在 EDT 中添加了两个按钮,但是在我调整它的大小之后,组件并没有添加到我的框架中(这会迫使 edt 更新其组件???原因是什么?这个?)。
所以即使在 edt 中我也没有得到我的新组件,但是当我在 edt 之外创建一个随机线程并使其更改某些 gui 元素属性(例如 setText)时,在 edt 之外就可以正常工作。
所以我的第一个问题是:为什么我的组件没有在 edt 中更新以及为什么它们在调整大小后可见
第二个:为什么我可以对 edt 之外的 swing 组件进行更改并且一切正常?这是否只是随机线程行为,例如在没有同步块的情况下一切正常,但是当您重新运行程序时,它最终会因为缺乏同步而崩溃。
【问题讨论】:
标签: java multithreading swing actionlistener event-dispatch-thread