我有一个扩展JFrame的主类。
我向这个框架实例添加了面板,它包含JTable和其他Swing组件。
在“ public static void main ”的主要课程中,我设置了swing事件派发线程。
我将面板添加到此实例框架,然后启动:
this.setTitle("Test");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
等...
一切都很好。
现在,对于JTable,它有一个监听器,当单击一行时,它会打开一个InfoDialog类的新实例。
在这个InfoDialog中,我像往常一样添加Swing组件。
我在JDialog中有另一个调度线程,如下所示:
class InfoDialog {
JDialog jd;
public void initGUI() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jd = new JDialog();
jd.setModalityType(ModalityType.APPLICATION_MODAL);
jd.setTitle("Buy");
jd.setDefaultCloseOperation(jd.DISPOSE_ON_CLOSE);
jd.pack();
jd.setLocationRelativeTo(null);
jd.setVisible(true);
}});
}
}
使用事件调度线程解决了我得到的错误(可能是因为它阻止了当前线程),我的问题是,这是正确的方法吗?
感谢您的任何建议。
答案 0 :(得分:2)
基本上,您应该只在Event Dispatching Thread的上下文中创建对话框(和所有其他UI组件)并与之交互。
您可以(在某种程度上)通过从EventQueue.invokeLater
方法调用main
来确保这一点。这确保了大部分UI已经在EDT的上下文中被调用。
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
//...Your UI code here...
}
});
}
应该可以安全地假设您在其他所有时间都在EDT内。调用者应该负责确保这一点,而不是您的组件。我经常创建“安全”工厂方法,以便更容易构建一些UI组件(例如进度指示器),这些组件的设计和记录都是线程安全的。
答案 1 :(得分:0)
只有一个AWT EDT。 (在Applet和WebStart中可以存在多个,但实际上只有一个。)
您的invokeLater
发生的事情是,EventQueue
上有一个事件,然后通过initGUI
的调用者返回执行,之前排队的事件将被调度,然后是run
{1}}方法已执行。
可能你应该将调用转移到代码的initGUI()
。