2012-03-01 8 views
11

Quando si dispone di un bus evento asincrono filo, e gli eventi del fuoco, diciamo all'interno del modello che vengono catturato nell'interfaccia utente probabilmente avete il seguente problema:modo migliore per combinare guava EventBus e AWT gestione degli eventi

La sede il gestore viene eseguito in un thread di lavoro, ma tutte le modifiche allo swing dell'interfaccia utente devono essere eseguite all'interno del thread di eventi AWT. Ciò significa che è necessario inserire tutti i clodi del gestore in EventQueue.invokeLater(...).

Questo assomiglia molto al codice della piastra della caldaia. Mi chiedo se esiste una soluzione più intelligente per questo problema.

Che dire di un'estensione del bus di eventi guava che contrassegna un gestore per l'esecuzione all'interno di un thread speciale? Questo potrebbe essere contrassegnato con un annotion, ad es. @ExecuteWithinEDT:

class EventBusChangeRecorder { 
    @Subscribe @ExecuteWithinEDT void recordCustomerChange(ChangeEvent e) { 
    recordChange(e.getChange()); 
    } 
} 

risposta

1

È possibile creare un EventBus che invia solo sul thread AWT:

EventBus mybus = new AsyncEventBus("awt", 
    new Executor() { 
     public void execute (Runnable cmd) { 
      if (EventQueue.isDispatchThread()) { 
       cmd.run(); 
      } else { 
       EventQueue.invokeLater(cmd); 
      } 
     } 
    }); 
+0

Ciao, lo stesso come con il mio altro commento al post di cui sopra: tutti gli eventi sono ora spediti in AWT. Quello che volevo era un modo in cui ogni singolo abbonato poteva decidere di inviare o meno in AWT. In caso contrario, un bus evento asincrono non avrebbe senso in un'app reale. – langm

9

I gestori registrati con un bus evento asincrono vengono eseguiti su qualunque discussione le previste Executor sceglie di eseguire loro su , non necessariamente un thread di lavoro.

Quello che ho fatto è stato creato un'implementazione di Executor che esegue roba sul thread della coda degli eventi. E 'piuttosto semplice:

public class EventQueueExecutor implements Executor { 
    @Override public void execute(Runnable command) { 
    EventQueue.invokeLater(command); 
    } 
} 

È possibile quindi solo creare il EventBus con quella:

EventBus eventBus = new AsyncEventBus(new EventQueueExecutor()); 

Poi saranno eseguiti tutti i gestori sul filo coda di evento.

Edit:

Un esempio di eventi di inoltro:

public class EventForwarder { 
    private final EventBus uiEventBus; 

    public EventForwarder(EventBus uiEventBus) { 
    this.uiEventBus = uiEventBus; 
    } 

    // forward all events 
    @Subscribe 
    public void forwardEvent(Object event) { 
    uiEventBus.post(event); 
    } 

    // or if you only want a specific type of event forwarded 
    @Subscribe 
    public void forwardEvent(UiEvent event) { 
    uiEventBus.post(event); 
    } 
} 

basta iscriversi che per il bus evento principale e post tutti gli eventi al bus evento principale, ma iscriversi tutti i componenti UI al Bus eventi UI.

+2

La soluzione è buona, ma offre un altro problema: ora TUTTI gli eventi vengono inviati all'interno di AWT. In un'applicazione del mondo reale, probabilmente vorrei che alcuni sottoscrittori venissero spediti all'interno di AWT (la parte della GUI) mentre altri sub-abbonati (dal modello o da un altro modulo) NON dovrebbero essere spediti all'interno di AWT. Altrimenti l'intero bus evento asincrono non avrebbe molto senso. – langm

+0

@langm: ​​un'opzione è di avere più 'EventBus'es ... uno che chiama i gestori sulla coda degli eventi e uno che non lo fa. I gestori che desiderano essere richiamati nella coda eventi si iscrivono a tale bus eventi. È quindi possibile avere un gestore o gestori che si abbonano al bus degli eventi OTHER e gestiscono determinati tipi di eventi pubblicandoli sul bus della coda degli eventi. – ColinD

+0

che probabilmente sarebbe una soluzione. ma vorrebbe dire, dovrei iscriversi due volte: una volta che l'interfaccia utente, una volta il bus dell'interfaccia utente dall'altro bus .... una bella funzionalità sarebbe una funzione di inoltro per inoltrare tutti gli eventi a livello globale a un altro bus. Ha senso ciò? – langm

Problemi correlati