В 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);
}
});
}
Почему? Есть ли какие-либо преимущества?
Правила, определяющие, что необходимо выполнить в 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 и т. д.
Эта строка модифицирует компонент Swing, поскольку ваш пользовательский фрейм является подклассом JFrame
:
new MyCustomFrameClass().setVisible(true);
Вообще, вы никогда не должны модифицировать компонент Swing, если вы не находитесь в потоке диспетчера событий (EDT).
Следующий код запустит все, что находится в Runnable
на EDT.
EventQueue.invokeLater(Runnable);
Теперь вызов setVisible(true)
будет выполняться на EDT, как и должно быть.