Должны ли мы использовать EventQueue.invokeLater для любого обновления графического интерфейса в настольном приложении Java? - PullRequest
16 голосов
/ 22 августа 2010

Я знаю, что при использовании этого метода параметр runnable передается в систему EventQueue. Но все ли обновления GUI должны выполняться с использованием этого метода? Я имею в виду, если я хочу сказать, изменить текст JButton, если я буду использовать что-то вроде этого:

java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
         jButton1.setText("changed text");
      }
});

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

Ответы [ 3 ]

26 голосов
/ 22 августа 2010

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

Предположим, у вас есть обработчикдля нажатия кнопки, и вы хотите изменить текст метки, когда кто-то нажимает кнопку.Тогда можно сохранить текст метки напрямую.Это возможно потому, что обработчик события нажатия кнопки запускается в потоке пользовательского интерфейса.

Предположим, однако, что при следующем нажатии кнопки вы запускаете другой поток , который выполняет некоторую работу и послеэта работа закончена, вы хотите обновить пользовательский интерфейс.Тогда вы используете invokeLater.Этот метод гарантирует, что ваше обновление пользовательского интерфейса выполняется в потоке пользовательского интерфейса.

Таким образом, во многих случаях вам не требуется invokeLater, вы можете просто напрямую обновлять пользовательский интерфейс.Если вы не уверены, вы можете использовать isDispatchThread, чтобы проверить, выполняется ли ваш текущий код в потоке диспетчеризации событий.

2 голосов
/ 22 августа 2010

Это нужно делать только в том случае, если вы еще не участвуете в потоке отправки событий. Если вы не запустили новые потоки или не выполнили код из основного потока, весь ваш код, вероятно, уже выполняется из потока диспетчеризации событий, что делает это ненужным. Например, все обработчики событий пользовательского интерфейса вызываются в потоке диспетчеризации событий, поэтому вам не нужно делать это для кода, вызываемого оттуда.

1 голос
/ 16 сентября 2011

Вместо того, чтобы по-настоящему избегать «повторения» (Java-люди, вероятно, сказали бы, читаемый код без многих секретов), вы можете использовать функцию шаблонов Eclipse. у меня есть его, чтобы расширить две буквы "ил" в следующем блоке:

EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    // do something.
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

Очевидно, такой дизайн очереди рассылки не только рекомендуется, но и в основном необходим. Это, пожалуй, самый шумный способ, которым я когда-либо видел на любом языке, когда я помещаю лямбду в очередь сообщений. Но это так. Это Ява. И в защиту Java, безусловно, из вышесказанного очевидно, что именно происходит. Я действительно недоволен количеством печатания, но единственное, что я могу придумать, чтобы избежать его, это макросы препроцессора C, и я держу пари, что людям на Java это не нравится. Расширение кода с помощью шаблонов более читабельно, поддерживается и не требует никакой черной магии.

...