SwingUtilities.invokeLater - PullRequest
       76

SwingUtilities.invokeLater

52 голосов
/ 26 августа 2011

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

Ответы [ 5 ]

52 голосов
/ 26 августа 2011

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

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

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

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

14 голосов
/ 26 августа 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(), за исключением жестких изменений в GUI (JTree & JTable), но только с Вещество L & F (отлично подходит для проверки согласованности событий на EDT)

  5. Базовый материал: Параллелизм в Swing

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

7 голосов
/ 26 августа 2011

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

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

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

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

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

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

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

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

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

7 голосов
/ 26 августа 2011

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

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

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

3 голосов
/ 26 августа 2011

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

...