JFrame не работает после создания первого экземпляра?

В рамках более крупного приложения я пишу класс настроек, который собирает и хранит пользовательские настройки. Этот класс является одноэлементным и создается при запуске приложения.

Чтобы принять ввод пользователя, два разных фрейма графического интерфейса создаются из ConfigSettings.java из общедоступного статического метода selectSettings (). Оба являются подклассами JFrame. Вот код для создания диалогового окна выбора файла:

private void selectFile() {
    SelectFileGUI fileSelector = new SelectFileGUI();
    fileSelector.setVisible(true);
    synchronized(this) {
        try {
            wait();
        }   catch(Exception e) {
            e.printStackTrace();
        }
    }
    fileSelector.dispose();
}

Это нормально работает при первоначальном запуске приложения. Однако позже пользователь может изменить выбранные настройки, в том числе выбрать новый исходный файл. Это делается повторным вызовом selectSettings ().

Проблема, с которой я сталкиваюсь, заключается в том, что любая последующая попытка создать и отобразить эти компоненты графического интерфейса снова приводит к отображению нового JFrame, но с серым фоном и без отображения кнопок или других компонентов. Во время отладки мне также не удавалось напрямую создавать новые экземпляры SelectFileGUI.

Что могло быть причиной такого поведения?


person deyur    schedule 02.02.2010    source источник
comment
Статичны ли какие-либо компоненты графического интерфейса? Если это так, они могут исчезнуть после того, как исчезнет первый JFrame. Ну, очевидно, не исчезли, но они могли быть отключены, когда JFrame исчез, поэтому они больше не находятся в отображаемом состоянии.   -  person Jonathan M Davis    schedule 02.02.2010


Ответы (4)


Я бы проверил, используете ли вы второй раз, когда вы его вызываете, поток графического интерфейса пользователя или вызов из одного из ваших собственных потоков.

В верхней части этого метода вы можете проверить его (поток AWT довольно легко идентифицировать по имени) и вызвать исключение, чтобы разработчики знали, что не следует вызывать его в неправильном потоке - или вы можете заблокировать их поток и сделать это. в рабочем потоке.

person Bill K    schedule 02.02.2010
comment
Большое спасибо, вы были совершенно правы. Обратив внимание на темы, я все разобрал :) - person deyur; 02.02.2010

Я не знаю, что вызывает такое поведение, но в вашем коде следующее просто не может быть правильным способом управления диалогами (подробнее ниже):

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 () ...} для управления чем-то таким простым, как селектор файлов / диалоговое окно, просто не может быть правильным.

person SyntaxT3rr0r    schedule 02.02.2010

Согласитесь с BillK: звучит так, как будто вы в первый раз вызываете его из-за пределов EDT (так что ваш вызов wait() не блокирует EDT), а затем из EDT во второй раз. См. SwingUtilities.invokeAndWait() и / или Dialog.setModal().

person Matt McHenry    schedule 02.02.2010

Все согласны с тем, что вы нарушаете правила, регулирующие использование потока рисования AWT (потока отправки событий).
Несколько замечаний:

  • Если ваш код пытается нарисовать ваши компоненты графического интерфейса за пределами этого потока рисования, серый диалог может быть результатом взаимоблокировки между EDT и потоком, который ваше приложение использует для рисования.
  • Если вы попадете в эту ситуацию, вы испытаете неспособность создавать новые диалоги, как описано.
  • Однако, когда вы упомянули, что при возникновении этой проблемы вы выполняете отладку, возможно, вы приостановили EDT через свою среду IDE.

Ознакомьтесь с этим руководством, чтобы получить некоторые рекомендации по как использовать потоки в клиентском приложении.

Чтобы полностью оценить проблему, было бы неплохо увидеть еще несколько кодов - например, относящиеся к делу части selectSettings().

person akf    schedule 02.02.2010