SwingUtilities.invokeLater

Мой вопрос связан с SwingUtilities.invokeLater. Когда я должен использовать его? Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса? Что именно он делает? Есть ли альтернатива ему, поскольку он не кажется интуитивно понятным и добавляет, казалось бы, ненужный код?


person FadelMS    schedule 25.08.2011    source источник
comment
Это эквивалент Control.BeginInvoke.   -  person SLaks    schedule 26.08.2011
comment
@SLaks Означает ли это, что если у меня есть один поток, мне не нужно его использовать?   -  person FadelMS    schedule 26.08.2011
comment
@FadelMS, поскольку фреймворки Swing порождают собственный поток (EDT), у вас всегда будет этот поток. (У вас нет цикла проверки сообщений, который обрабатывает клики пользователей и т. д., верно? Так как же вызываются различные методы actionPerformed? Согласно EDT!) Итак, когда вы говорите, что у вас есть < i>один поток, я должен был бы интерпретировать это, поскольку у вас только есть EDT (т.е. вы запустили графический интерфейс и упали с края основного метода). В этом случае НЕТ, вам не нужно использовать invokeLater. Однако вы не сможете выполнять какую-либо фоновую обработку. Если вы это сделаете, вы полностью заблокируете графический интерфейс...   -  person aioobe    schedule 02.09.2011
comment
возможный дубликат Что делает SwingUtilities.invokeLater?   -  person Barett    schedule 19.08.2015


Ответы (5)


Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса?

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

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

Swing в основном небезопасен для потоков. То есть все взаимодействие с этим API должно выполняться в одном потоке (EDT). Если вам нужно выполнять обновления графического интерфейса из другого потока (поток таймера, сетевой поток и т. д.), вам необходимо использовать такие методы, как тот, который вы упомянули (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).

person aioobe    schedule 25.08.2011
comment
@ Jens: Это означает, что я могу обойтись без него, если я нахожусь в том же потоке (Swing) или делаю что-то во время выполнения. - person FadelMS; 26.08.2011
comment
Ну, или делать что-то во время выполнения не очень точно. Если делать что-то в рантайме, скажем, в timer-thread, то нет, без таких методов не обойтись. - person aioobe; 26.08.2011

Swing is single threaded and all changes to the GUI must be done on EDT 

Основное использование для invokeLater()

  1. Основные методы всегда должны быть заключены в invokeLater()

  2. Отложенное (но асинхронное) действие/событие до конца EventQueue,

  3. Если EDT не существует, вам необходимо создать новый EDT, используя invokeLater(). Вы можете проверить это с помощью if (SwingUtilities.isEventDispatchThread()) {...

  4. Существует invokeAndWait(), но до сегодняшнего дня я (только мое мнение) не могу найти причину для использования invokeAndWait() вместо invokeLater(), за исключением жестких изменений в графическом интерфейсе (JTree и JTable), но только с Substance L&F (отлично подходит для проверки согласованности событий в EDT)

  5. Основные сведения: параллелизм в Swing

  6. Весь вывод фоновых задач должен быть заключен в invokeLater()

person mKorbel    schedule 25.08.2011

Каждое приложение Swing имеет как минимум 2 потока:

  1. Основной поток, выполняющий приложение
  2. EDT (поток диспетчеризации событий) — это поток, который обновляет пользовательский интерфейс (чтобы пользовательский интерфейс не зависал).

Если вы хотите обновить пользовательский интерфейс, вы должны выполнить код в EDT. Такие методы, как SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait, позволяют выполнять код с помощью EDT.

person Ammar    schedule 25.08.2011

Мой вопрос на этот раз связан с SwingUtilities.invokeLater: когда мне его использовать?

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

Вы должны использовать invokeLater() для отображения основного JFrame настольного приложения (например), вместо того, чтобы пытаться сделать это в текущем потоке. Это также создаст контекст для корректного закрытия приложения позже.

Вот и все для большинства приложений.

Должен ли я использовать каждый раз, когда мне нужно обновить компоненты графического интерфейса? Что именно он делает?

Нет. Если вы измените компонент GUI, он вызовет событие, которое регистрируется для последующей отправки Swing. Если для этого события есть прослушиватель, поток EDT вызовет его где-нибудь в будущем. Вам не нужно использовать invokeLater(), просто правильно настройте свои слушатели на компонентах.

Имейте в виду, что эта тема — та же самая тема для рисования рамок и т. д. на вашем экране. Следовательно, слушатели не должны выполнять сложные/длинные/интенсивные задачи, иначе ваш экран зависнет.

Есть ли альтернатива ему, поскольку он не кажется интуитивно понятным и добавляет, казалось бы, ненужный код?

Вам не нужно писать больше кода, чем отображать ваше приложение с invokeLater() + слушателями, которые вас интересуют, на компоненте. Остальное обрабатывается Swing.

person Jérôme Verstrynge    schedule 25.08.2011

Большинство инициируемых пользователем событий (щелчки, клавиатура) уже будут в EDT, поэтому вам не придется использовать для этого SwingUtilities. Это охватывает множество случаев, за исключением вашего потока main() и рабочих потоков, которые обновляют EDT.

person Garrett Hall    schedule 25.08.2011
comment
Что ж, пользователь может обновить файл, который отслеживается потоком, обновляющим графический интерфейс. - person Garrett Hall; 26.08.2011
comment
хм ... это не считается (прямым, вот где действует правило) событием, инициированным пользователем: пользователь обновляет файл (внутри свинга, в EDT) и сохраняет его (нажав кнопку, в EDT), который запускает уведомление о событии обновления файла ОС (внешнее качание, вне EDT), это уведомление достигает монитора (вне EDT), который отвечает за обновление графического интерфейса в EDT. - person kleopatra; 26.08.2011