Invoquer un code après l'exécution de tous les écouteurs d'événements de souris

StackOverflow https://stackoverflow.com/questions/1800264

  •  05-07-2019
  •  | 
  •  

Question

J'ai créé un panneau sur lequel un ensemble d'objets est dessiné. Chaque objet est ajouté en tant qu'écouteur d'événements de souris au panneau. Comme je le sais, lorsqu'un événement survient, les écouteurs sont informés et le code peut être (ou est?) Exécuté dans plusieurs threads. Est-il possible de joindre un code personnalisé qui sera exécuté après que tous les écouteurs aient fini d'exécuter leur code?

Était-ce utile?

La solution

Comme pour le commentaire Noel:

  

Une des préoccupations de cette technique peut se produire si une implémentation d'auditeur particulière renvoie une notification à l'avance et exécute le travail "hors bande". sur un fil séparé. Dans ce cas, la fin de l'appel de notification ne marque pas réellement la fin de l'exécution de l'auditeur. S'il s'agit d'une préoccupation réelle (c'est-à-dire que vous êtes au courant et préoccupez d'autres auditeurs élaborés définis par l'utilisateur qui font ce genre de chose, vous voudrez peut-être affiner et revisiter le problème.

En utilisant SwingUtilities.invokeLater () , vous êtes certain que le code est exécuté une fois que tous les écouteurs ont été avertis. Mais l'un de ces écouteurs peut effectuer son travail dans un thread séparé.

Si vous devez exécuter votre code après que tous les écouteurs aient été informés, ils ont terminé leur travail, vous pouvez faire quelque chose comme ceci:

pseudocode:

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

    -someTask()
        // perform some long task.

Si vous avez vos auditeurs comme

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

Si tous (ou certains) de vos auditeurs effectuent leur travail dans un autre thread. Votre ExecuteAtTheEnd est peut-être en train d'exécuter son code à la fin de la notification, mais pas à la fin de l'exécution du code des écouteurs.

Alors, que faites-vous?

Vous devez synchroniser l'utilisation d'un indicateur de verrouillage et exécuter votre code jusqu'à ce que cet indicateur ne soit plus utilisé.

Il peut s'agir d'un compteur incrémenté lorsque le programme d'écoute s'exécute et décrémenté lorsqu'il n'est pas:

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

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

Ensuite, vous continuez jusqu'à ce que ce drapeau soit faux:

  ExecuteAtTheEndListener implements MouseListener 

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

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

Bien sûr, c'est beaucoup plus compliqué que dans le pseudo-code, mais cela devrait fonctionner si vous êtes dans ce genre de situation.

Autres conseils

Est exécuté dans le même thread (le thread du répartiteur d'événements).

Pour faire ce que vous voulez, il vous suffit d'ajouter un auditeur supplémentaire et de le faire appeler "executeLater". méthode de la classe SwingUtilities .

Ce qui est fait, c'est attendre que le thread EDT termine les notifications puis appelle le code.

Pour le tester, ajoutez cet écouteur et voyez ce qu'il fait:

 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");
                }
            }
     }
 }

Certes, c’est un écouteur de souris que vous avez. Le concept est le même pour tous les autres auditeurs.

Je pense que ce que vous voudrez, c'est utiliser la méthode SwingUtilities.invokeLater () qui appellera une instance Runnable sur le thread Dispatch d'événement après le traitement de tous les autres événements de l'interface graphique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top