Domanda

Ho creato un pannello su cui è disegnato un insieme di oggetti. Ogni oggetto viene aggiunto come listener di eventi del mouse al pannello. Come so, dopo che si verifica un evento, gli ascoltatori vengono avvisati e il codice potrebbe essere (o è?) Eseguito in più thread. È possibile allegare un codice personalizzato che verrà eseguito dopo tutti gli ascoltatori avranno terminato di eseguire il loro codice?

È stato utile?

Soluzione

Come per il commento di Noel:

  

Una preoccupazione su cui questa tecnica potrebbe inciampare è se una particolare implementazione di listener restituisce una notifica in anticipo ed esegue lavori "fuori banda" su un thread separato. In tal caso, la fine della chiamata di notifica in realtà non segna la fine dell'esecuzione dell'ascoltatore. Se questa è una vera preoccupazione (vale a dire, sei a conoscenza e interessato ad altri ascoltatori elaborati definiti dall'utente che fanno questo genere di cose, potresti voler perfezionare e rivisitare il problema.

Usando il SwingUtilities.invokeLater () sei sicuro che il codice viene eseguito dopo che tutti gli ascoltatori sono stati avvisati. Ma uno di questi ascoltatori può svolgere il proprio lavoro in un thread separato.

Se devi eseguire il tuo codice dopo che tutti gli ascoltatori non solo sono stati avvisati ma hanno finito il loro lavoro, potresti fare qualcosa del genere:

pseudocodice:

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

    -someTask()
        // perform some long task.

Se hai i tuoi ascoltatori come

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

Se tutti (o alcuni) i tuoi ascoltatori eseguono il loro lavoro in un thread diverso. Il tuo ExecuteAtTheEnd potrebbe eseguire il suo codice alla fine della notifica, ma non alla fine dell'esecuzione del codice dei listener.

Quindi, cosa fai?

Devi sincronizzare l'uso di alcuni flag di blocco ed eseguire il tuo codice fino a quando quel flag non viene utilizzato.

Potrebbe essere un contatore che viene incrementato quando l'ascoltatore è in esecuzione e decrementato quando non lo è:

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

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

E poi procedi finché questo flag non è falso:

  ExecuteAtTheEndListener implements MouseListener 

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

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

Naturalmente è molto più complicato come lo inserisco nello pseudo-codice, ma dovrebbe funzionare, se ci si trova in questo tipo di circostanza.

Altri suggerimenti

Viene eseguito nello stesso thread (il thread dispatcher di eventi).

Per fare quello che vuoi devi solo aggiungere un listener extra e fare in modo che quel listener invochi " executeLater " metodo di SwingUtilities .

Ciò che fa è aspettare che il thread EDT finisca le notifiche e quindi invochi il tuo codice.

Per testarlo, aggiungi questo listener e guarda cosa fa:

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

Concesso, è un ascoltatore del mouse quello che hai. Il concetto è lo stesso per tutti gli altri ascoltatori.

Credo che ciò che vorrai è usare il metodo SwingUtilities.invokeLater () che invocherà un'istanza Runnable sul thread di invio degli eventi dopo che tutti gli altri eventi della GUI sono stati elaborati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top