JFrame не работает после первого создания? - PullRequest
1 голос
/ 02 февраля 2010

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

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

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

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

Ответы [ 4 ]

2 голосов
/ 02 февраля 2010

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

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

1 голос
/ 02 февраля 2010

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

fileSelector.setVisible(true);
    synchronized(this) {
        try {
            wait();
        }   catch(Exception e) {
            e.printStackTrace();
        }
    }
    fileSelector.dispose();

Хотите ли вы, чтобы ваши диалоги были модальными или нет?

Если вы хотите, чтобы они были модальными, тогда вы просто делаете блокирующий вызов, как при вызове JColorChooser.showDialog (...) метода, а возвращаемое «значение» - ваш цвет / файл /whatever.

Если вы хотите, чтобы они были немодальными, используйте обратный вызов, чтобы получить ваш цвет / файл. В примере с диалогом JColorChooser вы вызываете метод createDialog (...) и используете прослушиватели ok / cancel в качестве обратных вызовов.

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

http://java.sun.com/docs/books/tutorial/uiswing/components/colorchooser.html

Еще раз, это синхронизировано (это) {попытка {wait () ...} для управления чем-то таким простым, как селектор файлов / диалоговое окно, просто не может быть правильным.

0 голосов
/ 02 февраля 2010

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

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

Взгляните на этого руководства , где приведены рекомендации по использованию потоков в клиентском приложении.

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

0 голосов
/ 02 февраля 2010

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

...