Почему люди запускают графический интерфейс Java в очереди событий - PullRequest
9 голосов
/ 11 июня 2010

В Java, чтобы создать и показать новый JFrame, я просто делаю это:

public static void main(String[] args) {
   new MyCustomFrameClass().setVisible(true);
}

Однако я видел много людей, делающих это так:

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MyCustomFrameClass().setVisible(true);
       }
    });
}

Зачем?Есть ли преимущества?

Ответы [ 2 ]

8 голосов
/ 11 июня 2010

Правила, регулирующие то, что должно быть выполнено в EDT (я вижу, что «EDT» используется чаще, чем «Очередь событий»), изменились за время существования Java.И каждый раз, когда «правила» менялись, Sun советовала делать все больше и больше «связанных с GUI» работ над EDT.

Почему люди запускают Java GUI на EDT?

  • Потому что официальные рекомендации рекомендуют это делать.

  • Потому что это поможет избежать множества ошибок в потоке, связанных с GUI.

Обратите внимание, и это не очень хорошо известно, что EDT на самом деле время от времени дает сбой, потому что сам Swing имеет несколько ошибок.Каждое нетривиальное приложение Swing использует API-интерфейсы Swing, которые имеют, ну, в общем, ошибки, и, следовательно, время от времени EDT умирает.

Вы никогда этого не увидите, и это не вызывает проблем, потому что, когда EDTУмирает, он автоматически перезапускается.

По сути, делайте все, что связано с GUI, на EDT и выполняйте все длительные операции вне EDT (чтобы не блокировать EDT).

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

    JButton jb = ...
    jb.addActionListener( new ActionListener() {
        public void actionPerformed( final ActionEvent e ) {
          final Thread t = new Thread( new Runnable() {
           public void run() {
             // this shall get executed, after start() has been called, outside the EDT    
             }
           });
           t.start();
        }
    } );

Для более сложных примеров вы хотите прочитать на SwingWorker и т. Д.

4 голосов
/ 11 июня 2010

Эта строка изменяет компонент Swing, так как ваш пользовательский фрейм является подклассом JFrame:

new MyCustomFrameClass().setVisible(true);

Как правило, вам никогда не следует изменять компонент Swing, если вы не находитесь в потоке диспетчеризации событий (EDT).).

Следующий код будет запускать все, что находится в Runnable на EDT.

EventQueue.invokeLater(Runnable);

Теперь вызов setVisible(true) будет на EDT, как и должно.

...