Мой вопрос связан с SwingUtilities.invokeLater
. Когда я должен использовать его? Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса? Что именно он делает? Есть ли альтернатива ему, поскольку он не кажется интуитивно понятным и добавляет, казалось бы, ненужный код?
SwingUtilities.invokeLater
Ответы (5)
Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса?
Нет, если вы уже находитесь в потоке отправки событий (EDT), что всегда имеет место при реагировании на инициированные пользователем события, такие как клики и выбор. (Методы actionPerformed
и т. д. всегда вызываются EDT.)
Однако, если вы не находитесь в EDT и хотите выполнять обновления графического интерфейса (если вы хотите обновить графический интерфейс из какого-либо потока таймера или из какого-либо сетевого потока и т. д.), вам придется запланировать обновление, которое будет выполняться EDT. Вот для чего этот метод.
Swing в основном небезопасен для потоков. То есть все взаимодействие с этим API должно выполняться в одном потоке (EDT). Если вам нужно выполнять обновления графического интерфейса из другого потока (поток таймера, сетевой поток и т. д.), вам необходимо использовать такие методы, как тот, который вы упомянули (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).
Swing is single threaded and all changes to the GUI must be done on EDT
Основное использование для invokeLater()
Основные методы всегда должны быть заключены в
invokeLater()
Отложенное (но асинхронное) действие/событие до конца
EventQueue
,Если EDT не существует, вам необходимо создать новый EDT, используя
invokeLater()
. Вы можете проверить это с помощьюif (SwingUtilities.isEventDispatchThread()) {...
Существует
invokeAndWait()
, но до сегодняшнего дня я (только мое мнение) не могу найти причину для использованияinvokeAndWait()
вместоinvokeLater()
, за исключением жестких изменений в графическом интерфейсе (JTree и JTable), но только с Substance L&F (отлично подходит для проверки согласованности событий в EDT)Основные сведения: параллелизм в Swing
Весь вывод фоновых задач должен быть заключен в
invokeLater()
Каждое приложение Swing имеет как минимум 2 потока:
- Основной поток, выполняющий приложение
- EDT (поток диспетчеризации событий) — это поток, который обновляет пользовательский интерфейс (чтобы пользовательский интерфейс не зависал).
Если вы хотите обновить пользовательский интерфейс, вы должны выполнить код в EDT. Такие методы, как SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait, позволяют выполнять код с помощью EDT.
Мой вопрос на этот раз связан с
SwingUtilities.invokeLater
: когда мне его использовать?
Важно понимать, что в Java есть отдельный поток (EDT), обрабатывающий события, связанные с Swing.
Вы должны использовать invokeLater()
для отображения основного JFrame
настольного приложения (например), вместо того, чтобы пытаться сделать это в текущем потоке. Это также создаст контекст для корректного закрытия приложения позже.
Вот и все для большинства приложений.
Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса? Что именно он делает?
Нет. Если вы измените компонент GUI, он вызовет событие, которое регистрируется для последующей отправки Swing. Если для этого события есть прослушиватель, поток EDT вызовет его где-нибудь в будущем. Вам не нужно использовать invokeLater()
, просто правильно настройте свои слушатели на компонентах.
Имейте в виду, что эта тема — та же самая тема для рисования рамок и т. д. на вашем экране. Следовательно, слушатели не должны выполнять сложные/длинные/интенсивные задачи, иначе ваш экран зависнет.
Есть ли альтернатива ему, поскольку он не кажется интуитивно понятным и добавляет, казалось бы, ненужный код?
Вам не нужно писать больше кода, чем отображать ваше приложение с invokeLater()
+ слушателями, которые вас интересуют, на компоненте. Остальное обрабатывается Swing.
Большинство инициируемых пользователем событий (щелчки, клавиатура) уже будут в EDT, поэтому вам не придется использовать для этого SwingUtilities. Это охватывает множество случаев, за исключением вашего потока main() и рабочих потоков, которые обновляют EDT.
Control.BeginInvoke
. - person SLaks   schedule 26.08.2011actionPerformed
? Согласно EDT!) Итак, когда вы говорите, что у вас есть < i>один поток, я должен был бы интерпретировать это, поскольку у вас только есть EDT (т.е. вы запустили графический интерфейс и упали с края основного метода). В этом случае НЕТ, вам не нужно использоватьinvokeLater
. Однако вы не сможете выполнять какую-либо фоновую обработку. Если вы это сделаете, вы полностью заблокируете графический интерфейс... - person aioobe   schedule 02.09.2011