Почему люди выполняют Java GUI на Очереди событий

В 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);
       }
    });
}

Почему? Есть ли какие-либо преимущества?

9
задан Lahiru Ashan 28 November 2016 в 17:06
поделиться

2 ответа

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ вы просили привести пример того, как выполнить длинную операцию вне 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 и т. д.

8
ответ дан 2 November 2019 в 23:59
поделиться

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

new MyCustomFrameClass().setVisible(true);

Вообще, вы никогда не должны модифицировать компонент Swing, если вы не находитесь в потоке диспетчера событий (EDT).

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

EventQueue.invokeLater(Runnable);

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

4
ответ дан 2 November 2019 в 23:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: