Invocar un código después de que se ejecuten todos los oyentes de eventos del mouse

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

  •  05-07-2019
  •  | 
  •  

Pregunta

He creado un panel en el que se dibuja un conjunto de objetos. Cada uno de los objetos se agrega como un detector de eventos del mouse al panel. Como sé, después de que se produce un evento, se notifica a los oyentes y el código puede ejecutarse (¿o se ejecuta?) En varios subprocesos. ¿Es posible adjuntar un código personalizado que se ejecutará después de que todos los oyentes terminen de ejecutar su código?

¿Fue útil?

Solución

En cuanto al comentario de Noel:

  

Una preocupación con la que esta técnica podría tropezarse es si una implementación de escucha en particular devuelve una notificación antes de tiempo y ejecuta el trabajo "fuera de banda". en un hilo separado. En ese caso, el final de la llamada de notificación en realidad no marca el final de la ejecución del oyente. Si esta es una preocupación real (es decir, es consciente y está preocupado por otros oyentes elaborados y definidos por el usuario que hacen este tipo de cosas, es posible que desee refinar y revisar el problema.

Usando el SwingUtilities.invokeLater () está seguro de que el código se ejecuta después de que todos los oyentes fueron notificados. Pero uno de estos oyentes puede realizar su trabajo en un hilo separado.

Si necesita ejecutar su código después de que todos los oyentes no solo fueron notificados sino que terminaron su trabajo, podría hacer algo como esto:

pseudocódigo :

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

    -someTask()
        // perform some long task.

Si tiene sus oyentes como

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

Si todos (o algunos) de sus oyentes realizan su trabajo en un hilo diferente. Su ExecuteAtTheEnd puede estar ejecutando su código al final de la notificación, pero no al final de la ejecución del código de los oyentes.

Entonces, ¿qué haces?

Tiene que sincronizar el uso de alguna bandera de bloqueo y ejecutar su código hasta que esa bandera no se use.

Puede ser un contador que se incrementa cuando el oyente se está ejecutando y disminuye cuando no:

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

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

Y luego continúas hasta que esta bandera sea falsa:

  ExecuteAtTheEndListener implements MouseListener 

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

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

Por supuesto que es mucho más complicado, ya que lo puse en el pseudocódigo, pero debería funcionar, si estás en este tipo de circunstancias.

Otros consejos

Se ejecuta en el mismo hilo (el hilo del despachador de eventos).

Para hacer lo que quieras, solo tienes que agregar un oyente adicional y hacer que ese oyente invoque " executeLater " método de clase SwingUtilities .

Lo que hace es esperar a que el hilo EDT finalice las notificaciones y luego invoque su código.

Para probarlo, agregue esta escucha y vea lo que hace:

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

Por supuesto, es un oyente del mouse lo que tienes. El concepto es el mismo para todos los demás oyentes.

Creo que lo que querrás es usar el método SwingUtilities.invokeLater () que invocará una instancia ejecutable en el subproceso de distribución de eventos una vez que se hayan procesado todos los demás eventos de la GUI.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top