Как запустить JOptionPane в EDT?

У меня до сих пор возникают проблемы с пустыми JOptionPane. Судя по исследованиям в SO и Java Docs, это, очевидно, как-то связано с тем, что не используется расширение EDT. Мой вопрос в том, как именно EDT и его методы применяются к JOptionPane? Например, вывод ошибки терминала совершенно ясно показывает, что JOptionPane ниже не выполняется на EDT. Чего конкретно не хватает и как что-то вроде Runnable вписывается?

import javax.swing.*;
public class PaneDemo
{
public static void main(String[] args)
{
    final String[] TEXT ={
            //message
            "Hello, World!",
            //title
            "Greeting"};//end TEXT
    showMyPane(TEXT);
}//end main
public static void showMyPane(final String[] TEXT)
{
    JOptionPane.showMessageDialog(null, TEXT[0], TEXT[1], 
        JOptionPane.INFORMATION_MESSAGE);
    if(!SwingUtilities.isEventDispatchThread())
    {
        System.err.println("Err: GUI failed to use EDT.");
    }//end if(!SwingUtilities.isEventDispatchThread())
}//end showMyPane
}//end class PaneDemo

Ответ предложил добавить invokeLater. Однако это не очень хорошо отображается в BlueJ.

Снимок экрана BlueJ

Также isEventDispatchThread() по-прежнему возвращает ошибку в терминале. Это просто потому, что он сейчас находится не в том месте?


person Matt B    schedule 26.10.2012    source источник


Ответы (1)


Вы можете создать JOptionPane в потоке отправки событий следующим образом:

введите здесь описание изображения

  final String[] TEXT = {
        //message
        "Hello, World!",
        //title
        "Greeting"};//end TEXT

     ...

    /**
     * Create GUI and components on Event-Dispatch-Thread
     */
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
                JOptionPane.showMessageDialog(null, TEXT[0] 
                      + "\n is on EDT: " + SwingUtilities.isEventDispatchThread(), TEXT[1],
                        JOptionPane.INFORMATION_MESSAGE);
        }
    });

Взгляните на Урок: параллелизм в Swing , он должен помогите понять о чем речь

ОБНОВЛЕНИЕ:

в соответствии с комментарием вы должны инициировать JOptionPane на EDT при каждом вызове метода showPane(...) следующим образом:

   public static void showMyPane(final String[] TEXT) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JOptionPane.showMessageDialog(null, TEXT[0] 
                      + "\n is on EDT: " + SwingUtilities.isEventDispatchThread(), TEXT[1],
                        JOptionPane.INFORMATION_MESSAGE);
            }
        });
    }//end showMyPane

    public static void main(String[] args) {
        final String[] TEXT = {
            //message
            "Hello, World!",
            //title
            "Greeting"};//end TEXT
        showMyPane(TEXT);
    }
person David Kroukamp    schedule 26.10.2012
comment
"However if you only want to show a JOptionPane without any JFrame etc you don't need to use Event-Dispatch-Thread", вообще-то да, думаю, да. - person Hovercraft Full Of Eels; 26.10.2012
comment
@David Если EDT не требуется, что вызывает пустые панели JOptionPanes? Я уже читал Concurrency in Swing о Integer.MAX_VALUE раз. - person Matt B; 27.10.2012
comment
Вы также можете использовать SwingUtilities.invokeAndWait, если хотите заблокировать выполнение кода до тех пор, пока пользователь не ответит на диалоговое окно. - person MadProgrammer; 27.10.2012
comment
Дэвид: только если его API говорит, что это так. В прошлый раз, когда я смотрел, это не было упомянуто. - person Hovercraft Full Of Eels; 27.10.2012
comment
@HovercraftFullOfEels, вы правы, только что проверили, извините, другая ссылка ввела меня в заблуждение - person David Kroukamp; 27.10.2012
comment
@MattB извините, я ошибся, так как для пустых JOptionPanes я не уверен, опубликуйте SSCCE. Смотрите мой отредактированный пост - person David Kroukamp; 27.10.2012
comment
@Дэвид Не беспокойся! Что касается SSCCE, кажется, что это происходит совершенно случайно, поэтому код, который я уже опубликовал, — это лучшее, что я могу сделать. - person Matt B; 27.10.2012
comment
@Andrew Он будет блокироваться только в контексте, если EDT позволит вызывающему потоку продолжить работу. - person MadProgrammer; 27.10.2012
comment
Итак, как код, опубликованный для этого ответа, соответствует коду, который я разместил в вопросе? Другими словами, какие изменения мне теперь внести в showMyPane()? - person Matt B; 27.10.2012
comment
@MattB смотрите обновление. Кстати, пустое JOptionPane могло произойти из-за создания нескольких JOptionPane один за другим без использования EDT. - person David Kroukamp; 27.10.2012
comment
@MadProgrammer не рекомендуется использовать invokeAndWait, если когда-то было запущено EDT, invokeLater является самым безопасным, в противном случае необходимо проверить isEvent..., потому что invokeAndWait блокирует EDT, если он активен, чтобы попытаться вызвать invokeAndWait в EDT - person mKorbel; 27.10.2012
comment
@mKorbel Я согласен, но если вы уже выбрали синхронизацию обратного вызова с EDT (потому что вы проверили isEventDispatchingThread) и вас интересует результат возврата вызова, invokeAndWait — один из лучших вариантов. . - person MadProgrammer; 27.10.2012
comment
Просто любопытно, в чем причина javax.swing.SwingUtilities, а не просто SwingUtilities? Класс компилируется в любом случае. Хотя я еще не пробовал его запускать. - person Matt B; 27.10.2012
comment
@MattB это в основном похоже на встроенный импорт, вам все равно не нужно добавлять оператор imports javax.swing.... При желании вы можете уточнить импорт глобально, просто удалите часть javax.swing., а затем используйте ее в верхней части класса после объявления пакета import javax.swing.SwingUtilities;. - person David Kroukamp; 27.10.2012
comment
@MattB смотрите мое обновление, у вас есть SwingUtilities.isEventDispatchThread() за пределами SwingUtilities.invokeLater(...), поэтому он возвращает false - person David Kroukamp; 27.10.2012