Немодальный JDialog не показывает содержимое

(Java SE 6) Я пытаюсь создать всплывающее диалоговое окно, в котором отображается сообщение «подождите», пока моя программа выполняет трудоемкую работу. Для этого я решил использовать немодальный JDialog, чтобы программа продолжала работать и работала, пока JDialog виден (если вы используете модальный, программа остановится, пока диалог не будет закрыт пользователем) .

Проблема в том, что когда вы используете немодальный диалог таким образом, появляется JDialog с заголовком, но содержимое не появляется (я предполагаю, что они по какой-то причине не рисуются). Я пробовал вызывать repaint и т. д., но ничего не работает.

Теперь, по словам группы людей в Интернете, это настоящая ошибка Swing, и единственные ответы, которые я нашел, - это не делать что-то таким образом и найти какие-то другие способы уведомления пользователя об ожидании. Мне любопытно, сталкивался ли кто-нибудь здесь с этой проблемой раньше и нашел обходной путь.

Спасибо!


person Riemannliness    schedule 19.03.2011    source источник
comment
Ссылка на ошибку была бы полезна.   -  person trashgod    schedule 19.03.2011
comment
Я решил использовать немодальный JDialog, чтобы программа продолжала работать, пока JDialog виден. Модальное диалоговое окно не препятствует запуску любого потока в остальной части программы, а только доступ пользователя к элементам управления родителя. У меня есть 2D-анимации, которые продолжают рендеринг, пока пользователь вводит параметры конфигурации в JOptionPane.   -  person Andrew Thompson    schedule 19.03.2011
comment
@Эндрю Томпсон прав; вот краткий пример. Мне все еще любопытно, какую ошибку вы пытаетесь избежать.   -  person trashgod    schedule 19.03.2011


Ответы (4)


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

person trashgod    schedule 19.03.2011

Это не ошибка, вы должны выполнять свою работу с тяжелым весом и работу с легким весом в отдельном потоке рядом с основным потоком. Это необходимо из-за логических взаимосвязей между потоком графического интерфейса диалога и его отношением ActionListenerEvents к тяжелой работе в фоновом режиме. Если вы не отделите свой основной поток, он определит ничью Swing из-за некоторых событий уведомления. У меня была та же проблема, я пытался отслеживать ход загрузки FTP, который я начал из JFrame, чтобы показать его в JDialog.

Сначала я попробовал:

//Activated by Upload Button
public void actionPerformed(ActionEvent e) {

    if("Upload".equals(e.getActionCommand())){

    // some Declarations

    new Thread(){

        public void run() {
            /*Run JDialog with the Upload - ProgressBar*/
            FileUploadProgressBar fileUploadProgressBar = new FileUploadProgressBar(localFile, remoteFile, ftpPersistence);
        }
    }.start();

/*Run the heavy weigth Job - the Upload*/
ftpPersistence.uploadFile(localFile, remoteFile);

// ...
    }

//...

}

Но таким образом я получил JDialog FrameBorder и панель контента, но...

Следующая попытка:

//Activated by Upload Button
public void actionPerformed(ActionEvent e) {

    if("Upload".equals(e.getActionCommand())){

    // some Declarations

    new Thread(){

        public void run() {
        /*Run JDialog with the Upload - ProgressBar*/
        FileUploadProgressBar fileUploadProgressBar = new FileUploadProgressBar(localFile, remoteFile, ftpPersistence);
    }
}.start();


new Thread(){

    public void run() 
            /*Run the heavy weigth Job - the Upload*/
            ftpPersistence.uploadFile(localFile, remoteFile);
        }
    }.start();
    // ... 
    }
//...
}

и, наконец, это сработало, надеюсь, это поможет;)

person elfu    schedule 13.12.2012

Я использую это, и это работает - исходный код (без исправления, которое я нашел для перерисовки во время работы) взят отсюда: http://inversionconsulting.blogspot.com/2008/03/java-jdialog-and-jprogressbar-example.html

но я объединил его в (с небольшими изменениями):

JProgressBar pb = new JProgressBar(0,100);

pb.setPreferredSize(new Dimension(275,30));
pb.setString("Running");
pb.setStringPainted(true);
pb.setValue(0);

JLabel label = new JLabel("Progress: ");
JPanel center_panel = new JPanel();

center_panel.add(label);
center_panel.add(pb);

JDialog dialog = new JDialog((JFrame)null, "Working ...");

dialog.getContentPane().add(center_panel, BorderLayout.CENTER);
dialog.pack();
dialog.setVisible(true);
dialog.setLocationRelativeTo(null); // center on screen

In my code later on, when it is running through my loop (being 1 to 10 using the variable 'tot') I repaint the dialog, updating the progress bar as the program runs through the loop, thusly (this is not given on the above page link) (I am not using multiple threads, all of this is in the main thread):

//set progress bar
pb.setValue(tot*10);
//repaint it
dialog.getContentPane().paintAll(pb.getGraphics());

Чтобы найти это решение, потребовалось много времени, проб и ошибок. Надеюсь, это работает для вас, как и для меня.

person davejr    schedule 28.05.2011
comment
О да, при использовании последней версии java инициализация диалогового окна и его отображение происходит прямо в начале обработки моего цикла (перед входом), а в конце моего цикла, прямо за его пределами, я dialog.dispose(). - person davejr; 29.05.2011

Пробовали ли вы validate() (нужно после добавления компонентов в контейнер) ? Также рассмотрите возможность публикации исходного кода, чтобы мы могли его проверить. Удачи.

person KarolDepka    schedule 19.03.2011
comment
Да, я пробовал все формы вызова компонентов для рисования. Причина, по которой я не добавил исходный код, заключается в том, что я знаю, что это ошибка Swing, и я ищу либо альтернативные реализации (например, использование SwingWorker, как было предложено), либо кого-то, кто нашел обходной путь для этого. это не зависит от ОС - эта проблема не возникает на компьютере с Windows. - person Riemannliness; 19.03.2011
comment
Я чувствую, что должен быть обходной путь для этого, все еще используя JDialog. - person KarolDepka; 19.03.2011