1

作为一个更大的应用程序的一部分,我正在编写一个设置类,它收集和存储用户定义的设置。这个类是一个单例,并在应用程序启动期间被实例化。

为了接受用户输入,在 ConfigSettings.java 中实例化了两个不同的 GUI 框架,来自一个公共静态方法 selectSettings()。两者都是 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 的新实例。

什么可能导致这种行为?

4

4 回答 4

2

我会检查您第二次调用它时是使用 GUI 线程还是从您自己的线程之一调用。

在该方法的顶部,您可以对其进行测试(AWT 线程很容易通过名称识别)并让它抛出异常,以便开发人员知道不要在错误的线程上调用它——或者您可以阻止他们的线程并执行此操作在工作线程中。

于 2010-02-02T01:09:04.393 回答
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() ... }是不正确的。

于 2010-02-02T01:52:04.260 回答
0

同意 BillK:听起来你第一次是从 EDT 外部调用它(所以你的调用wait()不会阻塞 EDT),然后是第二次从 EDT 调用。见SwingUtilities.invokeAndWait()和/或Dialog.setModal()

于 2010-02-02T01:31:11.870 回答
0

这里的共识是,您违反了管理 AWT 绘制线程(事件调度线程)使用的规则。
有几点需要注意:

  • 如果您的代码尝试在此绘制线程之外绘制您的 GUI 组件,则灰色对话框可能是 EDT 和您的应用程序用于绘制的线程之间死锁的结果。
  • 如果您确实遇到这种情况,您将无法按照所述创建新对话框。
  • 但是,正如您提到您在遇到此问题时正在调试,可能是您通过 IDE 暂停了 EDT。

查看本教程,了解有关如何在客户端应用程序中使用线程的一些指南。

为了充分理解这个问题,很高兴看到更多与代码相关的部分selectSettings(),例如。

于 2010-02-02T02:21:50.050 回答