220 likes | 359 Views
La gestione degli eventi. Antonio Cisternino. Programmazione ad Eventi. Come abbiamo visto dagli esempi esiste un pattern comune ai vari sistemi per la gestione degli eventi La gestione degli eventi nelle interfacce si articola in: Gestione degli eventi all’interno dell’applicazione
E N D
La gestione degli eventi Antonio Cisternino
Programmazione ad Eventi • Come abbiamo visto dagli esempi esiste un pattern comune ai vari sistemi per la gestione degli eventi • La gestione degli eventi nelle interfacce si articola in: • Gestione degli eventi all’interno dell’applicazione • Gestione degli eventi del gestore dell’interfaccia grafica
Delegate Event Model • Questo modello, inizialmente introdotto da Java 1.1, è ormai quello più diffuso nei framework di programmazione di GUI • Il modello prevede: • Una sorgente degli eventi (es. il bottone) • I consumatori degli eventi • Delle interfacce (un modo di comunicazione concordato tra il produttore e il consumatore)
Schema di funzionamento Consumatori registrati Sorgente Eventi (es. Button) Listeners (interfaccia richiesta dalla sorgente)
Il pattern in Java • Il delegate event model può essere implementato in vari linguaggi • In Java è realizzato utilizzando: • Convenzione sui nomi dei metodi per registrare consumatori presso la sorgente (addXXXListener(XXXListener l)) • Interfaccia che la sorgente usa per comunicare l’evento (XXXListener) • Invocazione dell’evento: la sorgente invoca uno dei metodi dell’interfaccia XXXListener
Chi fa cosa • Produttore di eventi: • addXXXListener • removeXXXListener • Definisce una classe XXXEvent • Definisce l’interfaccia XXXListener • Consumatore di eventi • Implementa l’interfaccia XXXListener • Si registra presso il produttore
Il punto di vista dei controlli • Il delegate event model, ideale per chi usa controlli, presenta problemi nella gestione degli eventi dei controlli • Come si fa a rendere “trasparente”un controllo ad un evento? • Ad esempio: il click su una label potrebbe convenire che sia notificato alla finestra che lo contiene
Il bubbling di un evento si ha quando viene passato al contenitore di chi lo ha ricevuto In questo modo si possono implementare i comportamenti di default Si possono anche gestire in modo centralizzato eventi di un controllo composto da finestre Propagazione degli eventi
Tunneling • Framework come WPF (aka Avalon) supportano anche il flusso in direzione inversa al bubbling degli eventi: il tunneling • Questo flusso (solitamente seguito dal bubbling) offre la possibilità al contenitore di un controllo di gestire un evento prima che arrivi al figlio • Il gestore dell’interfaccia decide, per ogni tipo evento, se è diretto, se fa uso di bubbling, o tunneling e bubbling
Implementiamo il bubbling • Nei linguaggi orientati ad oggetti il bubbling viene facilmente scaricato sulla gerarchia dell’ereditarietà • Nei framework OO normalmente tutti I componenti grafici ereditano da una classe base, ad esempio Component • Dalla classe base tutti i componenti ereditano (direttamente o meno) un metodo deputato alla gestione degli eventi • Il componente vede passare tutti gli eventi a lui diretti, e può gestirli localmente o delegare
Un esempio • Java, nella sua prima versione (fino alla versione 1.0.2) aveva un modello di gestione degli eventi come OWL (Borland) e MFC (Microsoft) basato su bubbling • La possibilità di invocare il metodo della superclasse consente di delegare la gestione di un evento non gestito (o solo parzialmente gestito) • Il dispatch e la classificazione degli eventi viene tipicamente incapsulato da metodi invocati dal metodo che gestisce gli eventi, inclusa la delega
Java AWT Event Model class Component { int x, y; bool handleEvent(Event e); } class Button extends Component { String text; bool handleEvent() { } … } class Window extends Component class Frame extends Window
Event handling class MyButton extends Button { boolean handleEvent(Event e) { switch (e.type) { case Event.MOUSE_UP: … return true; // Event handled! } default: return super.handleEvent(e); }}
Dal bubbling alla delegation • I controlli, nella gestione degli eventi, possono implementare l’interfaccia necessaria per essere una sorgente di eventi • Per fare questo si possono intercettare gli eventi, ed invocare il metodo dei consumatori registrati • La delegation migliora le performance: la gestione degli eventi non necessita l’introduzione di nuove classi
L’event loop • Chi invoca gli event handler? • Un thread dell’applicazione spende una porzione significativa del suo tempo nell’event loop • L’event loop ha la seguente struttura: while (m=PickMessage()) DispatchMessage(m) • Un qualche metodo (più o meno nascosto) esegue questo ciclo
L’event loop • Normalmente l’event-loop viene incapsulato in qualche classe (Application.Run per .NET, SwingUtilities.invokeLater in Java) • La funzione di dispatch del messaggio si occupa di inoltrare il messaggio al componente dell’applicazione interessato • Questo innesca il meccanismo di chiamate che poi va a chiamare gli event handler definiti dall’applicazione
Thread or threads? • Quanti thread gestiscono l’event loop? • A dispetto dell’apparente concorrenza degli eventi il thread della UI è uno • Se un event handler lo blocca l’intera interfaccia dell’applicazione smette di funzionare • Se quindi è necessario intraprendere un qualche lavoro significativo è bene avviare un thread nell’event handler a cui delegare il compito
Troviamo il colpevole • Come fa il gestore dell’interfaccia a individuare il destinatario di un evento? • Input da tastiera: il controllo che ha il focus riceve il messaggio • Spesso il focus si ottiene evidenziando il controllo • Usando il tab è possibile spostare il focus su altri controlli • La pick correlation consiste nell’associare un evento del puntatore con il controllo a cui è diretto
Pick Correlation • Come facciamo a sapere quale controllo deve ricevere gli eventi del puntatore? • Abbiamo a disposizione le coordinate del punto (x, y), ma non sono sufficienti! • Siamo tutti abituati a sovrapporre finestre: qual’è quella visibile? • Il gestore dell’interfaccia organizza in modo appropriato le finestre e per ciascuna ricorda lo z-index ovvero un indice che indica l’ordinamento lungo l’asse Z
Finestre e Z-Ordering • La struttura dati primitiva delle interfacce grafiche (fino ad oggi…) è la finestra: un’area rettangolare dello schermo • Tutti i controlli non sono altro che finestre specializzate • Per trovare a quale finestra corrisponde un punto (x, y) sullo schermo è necessario • trovare tutte le finestre che lo contengono • tra queste prendere quella con z-index più alto • Le finestre sono organizzate in un albero che consenta l’implementazione della ricerca in modo più efficiente (sfruttando il contenimento)
Spy++ è un tool Microsoft (ne esistono analoghi per X-Windows) che consente di monitorare gli eventi diretti a finestre È anche possibile analizzare la struttura di un’applicazione in termini di finestre Usare Spy++
Osserviamo gli eventi • Se abilitiamo il log degli eventi su un bottone della calcolatrice notiamo che: • Gli eventi di paint arrivano in momenti inattesi • Ci sono molti tipi di eventi • Se invece facciamo il log della finestra vediamo in azione il bubbling: alcuni eventi sui figli sono inviati anche al padre