Параллелизм Swing и поток событий

Интересно, что является наиболее приемлемым способом правильно работать с Java Swing. Я знаю, что в приложении Java Swing по умолчанию есть два потока: Основной поток и Event-Dispatch. Я создаю и показываю окно таким образом.

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new MyWindow().initializeAndShow());
    }

Но я хочу знать, как я должен работать с Java Swing во время выполнения. Я имею в виду, например, установку текста в JText по нажатию кнопки. Мне нужно делать это все время?

  SwingUtilities.invokeLater(()-> button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e)
            {

               SwingUtilities.invokeLater(()-jtext.setText("HelloFromAWTThread");
            }
        });      

Это правильно, я думаю, что кнопка также является частью пользовательского интерфейса, поэтому слушатель должен быть установлен в потоке диспетчеризации, или это не правильно? А установка JText также должна быть в потоке AWT?

1 ответ

Решение

Это намного проще, чем вы думаете.

Конечно, изменения элементов пользовательского интерфейса (например, установка текста метки, добавление слушателя к кнопке и т. Д.) Должны выполняться только потоком отправки событий (EDT).

Но в большинстве случаев это не является реальным ограничением, так как все события (например, щелчок мыши по кнопке или нажатие клавиши) обрабатываются EDT, поэтому ваши слушатели также исполняются в EDT.

Так что если вы хотите зарегистрировать слушателя, просто сделайте

button.addActionListener(new ActionListener() {
    /* called by the EDT when the button has been clicked */
    public void actionPerformed(ActionEvent e) {
        jtext.setText("HelloFromAWTThread");
    }
});

Или еще проще с Java 8 лямбды:

button.addActionListener(e -> jtext.setText("HelloFromAWTThread"));

Это становится все более сложным, если вы хотите выполнить долгосрочную задачу, например, трудоемкие вычисления (вычисление 1 миллиона цифр PI, выполнение простой разложения и т. Д.), Любую операцию ввода-вывода (загрузка файла, выполнение сетевой запрос) или любая операция блокировки, так как это будет слишком долго занимать EDT и не позволит ему обрабатывать события пользовательского интерфейса. Поэтому эти задачи должны выполняться в отдельных потоках. Но поскольку не разрешено обновлять пользовательский интерфейс из других потоков, кроме EDT, вы можете "передать" задачу обновления пользовательского интерфейса в EDT, вызвав SwingUtilities.invokeLater(updateTask),

Другие вопросы по тегам