作为更大的应用程序的一部分,我正在编写一个设置类,它收集并存储用户定义的设置。此类是单例,并在应用程序启动期间实例化。
为了接受用户输入,在ConfigSettings.java中从公共静态方法selectSettings()中实现了两个不同的GUI框架。两者都是JFrame的子类。以下是文件选择对话框实例化的代码:
private void selectFile() {
SelectFileGUI fileSelector = new SelectFileGUI();
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
}
这在最初运行应用程序时工作正常。但是,稍后用户可以改变他们选择的设置,包括选择新的源文件。这是通过再次调用selectSettings()完成的。
我遇到的问题是,任何后续再次实例化和显示这些GUI组件的尝试都会导致显示新的JFrame,但背景为灰色,并且没有显示任何按钮或其他组件。在调试时,我也无法直接创建SelectFileGUI的新实例。
可能导致这种行为的原因是什么?
答案 0 :(得分:2)
我会检查你第二次调用它是否正在使用GUI线程或从你自己的一个线程调用。
在该方法的顶部,您可以测试它(AWT线程很容易通过名称识别)并让它抛出异常,因此开发人员知道不要在错误的线程上调用它 - 或者您可以阻止它们的线程并在工作线程中完成。
答案 1 :(得分:1)
我不知道造成这种行为的原因是什么,但在您的代码中,以下几乎不可能成为管理对话框的正确方法(详见下文):
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
您希望对话框是模态的吗?
如果你想要它们是模态的,那么你只需要调用阻塞调用,就像你调用 JColorChooser.showDialog(...)方法一样,你的返回“值”是你的颜色/文件/不管。
如果你想要它们是非模态的,那么你使用回调来获取你的颜色/文件。在JColorChooser对话框示例中,您将调用createDialog(...)方法并使用ok / cancel侦听器作为回调。
我建议你看看sun的教程,例如关于颜色选择器的教程,看看如何正确显示模态(或非模态)对话框:
http://java.sun.com/docs/books/tutorial/uiswing/components/colorchooser.html
再一次, synchronized(this){try {wait()...} 来管理像文件选择器/对话框一样简单的东西是不正确的。
答案 2 :(得分:0)
同意BillK:听起来你是第一次从EDT以外的地方打电话给你(因此你对wait()
的呼叫不会阻止EDT),然后第二次从EDT开始。请参阅SwingUtilities.invokeAndWait()
和/或Dialog.setModal()
。
答案 3 :(得分:0)
这里的共识是你违反了管理AWT绘画线程(事件调度线程)使用的规则。
有几点需要注意:
查看this tutorial以获取有关如何在客户端应用程序中使用线程的一些指导原则。
要完全理解这个问题,很高兴看到selectSettings()
的更多与代码相关的部分,例如。