Вызвать код после того, как все слушатели мыши будут выполнены - PullRequest
0 голосов
/ 26 ноября 2009

Я создал панель, на которой нарисован набор объектов. Каждый объект добавляется в качестве прослушивателя событий мыши на панель. Как я знаю, после того, как событие происходит, слушатели уведомляются, и код может быть (или есть?) Выполнен в нескольких потоках. Можно ли прикрепить пользовательский код, который будет выполнен после , когда все слушатели завершат выполнение своего кода?

Ответы [ 3 ]

3 голосов
/ 26 ноября 2009

Выполняется в том же потоке (потоке диспетчера событий).

Чтобы сделать то, что вы хотите, вам просто нужно добавить дополнительного слушателя и заставить этот слушатель вызывать метод executeLater SwingUtilities class.

Что делает, это дождется, пока поток EDT завершит уведомления, а затем вызовет ваш код.

Чтобы проверить это, добавьте этот слушатель и посмотрите, что он делает:

 class MouseListener extends MouseAdapter {
     public void mouseClicked(MouseEvent e)  {
           // System.out.println("If uncommented this would be invoked with the rest of the listners");
           SwingUtilities.invokeLater( new Runnable() {
                public void run() {
                    System.out.println("Invoked after all the listeners were notified");
                }
            }
     }
 }

Конечно, это слушатель мыши, что у вас есть. Эта концепция одинакова для всех остальных слушателей.

1 голос
/ 26 ноября 2009

Что касается комментария Ноэля:

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

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

Если вам нужно выполнить код после того, как все слушатели не только были уведомлены, но и закончили свою работу, вы можете сделать что-то вроде этого:

псевдокод:

Listener implements MouseListener 
    +mouseClicked( event: MouseEvent ) 
        SwingUtilities.invokeLater( // returns immediately 
              someTask() 
        )

    -someTask()
        // perform some long task.

Если у вас есть слушатели как

 addListener( new Listener() )
 addListener( new Listener() )
 addListener( new Listener() )
 addListener( new ExecuteAtTheEnd() ) 

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

Итак, что вы делаете?

Вы должны синхронизировать использование какого-либо флага блокировки и выполнять ваш код, пока этот флаг не будет использован.

Это может быть счетчик, который увеличивается, когда слушатель выполняется, и уменьшается, когда нет:

 Listener implements MouseListener 
    +mouseClicked( event: MouseEvent )
        lockFlagCount++ 
        SwingUtilities.invokeLater( 
              someTask() 
        )

    -someTask()
        // perform some long task.
        lockFlag--

А затем вы просто продолжаете, пока этот флаг не станет ложным:

  ExecuteAtTheEndListener implements MouseListener 

       + mouseClicked( event: MouseEvent ) 
        SwingUtilities.invokeLater( 
              executeAtTheEnd() 
        )
       - executeAtTheEnd() 
            while( logFlagCount > 0 ) 
                wait()

             if( logFlagCount == 0 ) 
                 // continue with the task.                  

Конечно, все гораздо сложнее, поскольку я помещаю его в псевдокод, но оно должно работать, , если Вы находитесь в таких обстоятельствах.

0 голосов
/ 26 ноября 2009

Я считаю, что вам нужно использовать метод SwingUtilities.invokeLater(), который вызовет экземпляр Runnable в потоке диспетчеризации событий после обработки всех других событий графического интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...