Подтвердить что ты не робот

InvokeAndWait в SwingUtilities

Пожалуйста, объясните метод invokeAndWait() в SwingUtilities. Я не могу это понять. Объясните это очень четко. Было бы очень полезно, если вы попробуете пример.

Отредактировано, чтобы добавить расширение @noob вопроса:

Что не ясно о этом?

Здесь приведен пример использования:

import javax.swing.SwingUtilities;

public class InvokeAndWaitStuff 
{
    public static void main(String[] args)
    {
        final Runnable doHelloWorld = new Runnable() {
             public void run() {
                 System.out.println("Hello World on " + Thread.currentThread());
             }
         };

         Thread appThread = new Thread() {
             public void run() {
                 try {
                     SwingUtilities.invokeAndWait(doHelloWorld);
                 }
                 catch (Exception e) {
                     e.printStackTrace();
                 }
                 System.out.println("Finished on " + Thread.currentThread());
             }
         };
         appThread.start();
    }
}

Вывод:

Hello World on Thread[AWT-EventQueue-0,6,main]
Finished on Thread[Thread-0,5,main]

И почему это важно?:

Причиняет doHelloWorld.run() выполняется синхронно на AWT поток событий. Этот вызов блокирует все ожидающие события AWT были обработаны и (затем) doHelloWorld.run() возвращается. Эта метод следует использовать, когда прикладной нити необходимо обновить GUI.

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

4b9b3361

Ответ 1

Чтобы понять, что делает invokeAndWait(), вам сначала нужно понять модель событий/потоков Swing.

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

В Swing этот специальный поток GUI называется Thread Dispatch Thread, или EDT. Он запускается, как только отображается компонент верхнего уровня Swing, и базовый рабочий поток, который имеет очередь FIFO объектов событий, которые он выполняет один за другим.

Когда графический интерфейс Swing должен быть нарисован или обновлен, JRE помещает событие в очередь EDT. Действия пользователя, вызывающие вызов слушателей, начинаются как события в очереди EDT. И (это важная часть), все, что ваша программа делает с изменением графического интерфейса (например, регистрация слушателей, добавление/удаление компонентов графического интерфейса пользователя или изменение данных модели, отображаемых графическим интерфейсом), должны быть помещены в очередь EDT или GUI может получить поврежден.

И теперь для финиша: invokeAndWait() помещает Runnable, который вы передаете ему в очередь событий EDT, и ждет, пока EDT не выполнит его.. Это следует использовать, Поток GUI должен делать что-то, что влияет на графический интерфейс, но также нужно подождать, пока оно не будет выполнено до его продолжения. Если вы просто хотите сделать что-то, что влияет на графический интерфейс, но все равно, когда оно будет закончено, вы должны использовать invokeLater().

Ответ 2

У меня была аналогичная проблема в JTable. Программа была заблокирована где-то в методе scrollRectToVisible. Я заменил вызов, обернув его вызовом invokeLater. InvokeAndWait не разрешил проблему с блоком.

    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            table.scrollRectToVisible(r);
        }

    });