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
Propagazione degli eventi
 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
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)
Usare Spy++
Spy++ è un tool
Microsoft (ne esistono
analoghi per XWindows) che
consente di
monitorare gli eventi
diretti a finestre
È anche possibile
analizzare la struttura
di un’applicazione in
termini di finestre
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
Scarica

4 - La gestione degli eventi