MokaByte
Numero
16 - Febbraio 1998
|
|||
|
eventi per delega |
||
Daniela Ruggeri |
|
||
Dopo l'ottimo articolo
di Massimo Carli sul numero di MokaByte di Febbraio 1997
ho ritenuto necessario scrivere un articolo di completamento che mettesse
a confronto le differenze tra le due gestioni di eventi.
L'articolo
si rivolge a quanti ancora non hanno familiarità con la nuova gestione
degli eventi a delega e sono restii per tale motivo ad abbandonare la vecchia.
Introduzione.
In questo articolo
vengono affrontate le differenze tra la vecchia gestione degli eventi riguardante
il package AWT 1.0 e la nuova (Delegation Event Model) riguardante il package
AWT 1.1.
Nella vecchia
gestione esiste solo un evento che viene intercettato ed elaborato da appositi
metodi associati all'oggetto coinvolto (target). Questi metodi sono generici
(action() e handleEvent()) o specializzati sul particolare
evento (es. mouseDown(), keyPress(), ecc.) e si trovano solamente
solamente nella classe che li ospita.
Ogni metodo
che gestisce l'evento è di tipo booleano e quando restituisce true
tutto finisce, quando invece restituisce false e l'evento viene
spedito al contenitore dell'oggetto, e questa fase si ripete fino a quando
il metodo opportuno restituisce true o fino a quando non esistono
più contenitori.
Con la nuova
gestione degli eventi in AWT 1.1. esistono delle classi che hanno associata
una lista di ascoltatori (ne esiste una specifica per ogni tipo di evento
per esempio TextListener), ed esistono delle classi che si iscrivono
a quella lista. In questo modo ogni evento trattato dalla lista che viene
intercettato dalla prima classe, viene "sentito" da tutte le classi registrate
nella lista.
La novità
della nuova gestione quindi consiste nell'avere più classi che possono
essere interessate all'evento che si registrano come ascoltatori alla lista
opportuna, e possono essere notificate tutte al momento del verificarsi
dell'evento. Nella vecchia gestione invece le sole classi notificate erano
quella che conteneva i metodi per la gestione dell'evento, ed eventualmente
i successivi contenitori.
Un'altra novità
che riguarda la nuova gestione di eventi, al di fuori dell'AWT, è
la possibilità di creare eventi nuovi estendendo l'interfaccia EventObject
gestiti da una nuova interfaccia ascoltatrice estensione dell'interfaccia
EventListener. In uno dei capitoli successivi verrà spiegata
in breve questa possibilità.
In figura 1
e 2 è rappresentata la differenza tra le due gestioni. Come potete
vedere nella gestione vecchia tutti gli eventi vengono intercettati dal
metodo handleEvent(), mentre nella nuova vengono intercettati solo quelli
per cui esiste una lista a cui si sono registrati degli ascoltatori.
Figura 1.
Figura 2.
A chi assolutamente
non ha alcun idea circa la nuova gestione, presenterò una breve
storiella.
Supponiamo che
io voglia far sapere un certo numero di persone la data in cui avverrà
la prossima Conferenza su Java (evento = prossima Conferenza Java).
Allora ho bisogno
di annotarmi tutti i dati (nominativi e indirizzi delle persone), e quindi
prenderò un foglio (lista ascoltatrice) per tale scopo. Siccome
anch’io sono interessata all’evento la prima cosa che farò è
inserire il mio nominativo; dopo di che se conosco i dati delle persone,
non farò altro che aggiungerli direttamente alla lista, altrimenti
farò in modo di far avere la lista agli interessati affinché
loro stessi possano aggiungere i loro dati. Naturalmente posso anche aver
comunicazioni di ripensamento da parte delle persone che non vogliono più
partecipare alla Conferenza; in questo caso non farò altro che cancellarle
dalla lista.
Terminata la
lista, non mi rimarrà che attendere il verificarsi dell’evento,
e non appena l'organizzatore della conferenza mi avviserà comunicandomi
la data e i dati relativi, io non farò altro che inviare un avviso
postale a tutti gli indirizzi delle persone iscritte nella lista.
In questa storiella
io sono la classe sorgente dell'evento, detentrice della lista ascoltatrice
e quindi di tutti i metodi necessari a gestirla. Dato che le liste hanno
un nome xxxxxxListener, potremmo chiamarla ProssimaConferenzaJavaListener
che estende l’interfaccia EventListener. L’evento che gestirà
questa lista discende come tutti gli eventi dalla classe EventObject
che hanno un nome xxxxxxEvent; quindi questo evento avrà
nome ProssimaConferenzaJavaEvent.
Le persone iscritte
nella lista non sono altro che le istanze di classi interessate al verificarsi
dell’evento e i loro dati riguardano i loro handle. Le istanze vengono
inserite nella lista tramite il metodo addProssimaConferenzaJavaListener(ProssimaConferenzaJavaListener
pcj) e rimosse tramite il metodo removeProssimaConferenzaJavaListener(ProssimaConferenzaJavaListener
pcj)
Chi è
a questo punto il responsabile dell’avviso dell’evento? Non è altro
che una qualsiasi istanza di classe che mi spedisce la notifica richiamando
un mio metodo, che non fa altro che spedire la notizia con tutti i dati
relativi all’indirizzo specificato richiamando un metodo particolare dedicato
alla gestione dell’evento considerato, per esempio potremmo chiamarlo ProssimaConferenzaJavaPerformed
gestore dell'evento ProssimaConferenzaJavaEvent che è
un evento che fa parte della nostra lista (ci si aspetta di trovare questo
metodo associato all'handle della classe iscritta, esattamente come un
postino si aspetta di trovare una casella postale all’indirizzo di riferimento)
in cui vengono eseguite tutte le istruzioni che la classe iscritta aveva
stabilito di fare (la persona dalla casella postale prende delle decisioni
in funzione dei dati iscritti). Spiegheremo più in dettaglio questa
filosofia nell'ultimo paragrafo.
La
gestione eventi AWT con il JDK 1.0
Come accennato
nell'introduzione, con la gestione degli eventi AWT 1.0 la classe che gestisce
l'evento è l'unica alla quale viene notificato l'evento.
La prassi che
viene seguita quando un evento occorre è spiegata di seguito.
Viene eseguita
una chiamata al metodo nativo del toolkit window Container.deliverEvent()
che determina che Component sorgente deve essere passato come
dato dell'evento.
Quando il Component
viene identificato il metodo Component.postEvent() spedisce l'evento
al Component invocando il metodo handleEvent(). Qui di seguito
è riportato il codice del metodo all'interno della classe Component:
public boolean handleEvent(Event evt) {switch (evt.id) {
case Event.MOUSE_ENTER:
return mouseEnter(evt, evt.x, evt.y);
case Event.MOUSE_EXIT:
return mouseExit(evt, evt.x, evt.y);
case Event.MOUSE_MOVE:
return mouseMove(evt, evt.x, evt.y);
case Event.MOUSE_DOWN:
return mouseDown(evt, evt.x, evt.y);
case Event.MOUSE_DRAG:
return mouseDrag(evt, evt.x, evt.y);
case Event.MOUSE_UP:
return mouseUp(evt, evt.x, evt.y);
case Event.KEY_PRESS:
case Event.KEY_ACTION:
return keyDown(evt, evt.key);
case Event.KEY_RELEASE:
case Event.KEY_ACTION_RELEASE:
return keyUp(evt, evt.key);
case Event.ACTION_EVENT:
return action(evt, evt.arg);
case Event.GOT_FOCUS:
return gotFocus(evt, evt.arg);
case Event.LOST_FOCUS:
return lostFocus(evt, evt.arg);
}
return false;
}
A questo punto se la classe contenitore (esempio Applet) ha ridefinito il metodo handleEvent(), questo sarà il metodo richiamato. Esempio:
public MiaApplet extends Applet {Come si può notare nell'applet il metodo handleEvent() è stato ridefinito, quindi non appena verrà cliccato sul bottone MioBottone la notifica arriverà al contenitore MiaApplet e verrà eseguito il metodo handleEvent()....
Button MioBottone = new Button("OK");
...
public boolean handleEvent(Event evt) {
if (event.target == MioBottone && evt.id == Event.ACTION_EVENT) {
// fa qualcosa
}
....
}
}
public NuovoBottone exteds Button {A questo punto la notifica arriverà prima al bottone e poi se il metodo handleEvent() restituirà false il controllo verrà ceduto all'applet....
public boolean handleEvent(Event evt) {
...
}
}
public MiaApplet extends Applet {
...
NuovoBottone MioBottone = new NuovoBottone("OK");
...
}
Per quanto riguarda l'evento, tutte le informazioni passate ai vari metodi gestori sono contenute nella classe java.awt.Event .
Nella tabella
che segue sono descritte tali informazioni:
|
|
arg | Contiene specifici valori a secondo del componente. Per esempio nel caso di un TextField contiene il testo e nel caso di un CheckBox contiene lo stato. |
clickCount | E' il numero di click effettuati con il mouse nel caso di evento MOUSE_DOWN |
evt | Nel caso di piu' eventi indica quale sia il prossimo. |
modifiers | Mostra
lo stato dei tasti speciali ALT, CTRL, META e SHIFT
Puo' assumere i seguenti valori: ALT_MASK
|
id | Identificatore
dell'evento.
Può assumere i valori che seguono. ACTION_EVENT
|
key | Nel
caso di eventi che riguardano la tastiera identificano il codice del tasto
premuto.
Possono assumere i seguenti valori: F1, F2, … F12
|
target | Oggetto sorgente dell'evento |
when | E' l'orario in cui avviene l'evento |
x, y | Coordinate all'interno del componente dove l'evento occorre |
La
nuova gestione eventi AWT con il JDK 1.1
Nella
nuova gestione degli eventi, questi sono generati da una sorgente
di eventi. Uno o più ascoltatori possono registrarsi per essere
avvertiti quando quel particolare evento occorre. Questo modello è
anche chiamato a delega perché permette al programmatore
di delegare la gestione di un evento ad un determinato oggetto che implementi
un'appropriata interfaccia ascoltatrice. Nel nuovo modello di eventi AWT
tutti gli eventi sono estensioni della classe java.awt.AWTEvent.
In figura 3 sono rappresentanti tutti gli eventi e nella tabella
successiva sono raccolte le descrizioni di tali eventi.
Figura 3.
|
|
|
|
ComponentEvent | Al momento di nascondere, muovere, ridimensionare, mostrare componenti | ComponentListener | Component |
ContainerEvent | Al momento dell’aggiunta, rimozione di un componente al contenitore | ContainerListener | Container |
FocusEvent | Al momento che un componente prende o perde il fuoco | FocusListener | Component |
KeyEvent | Al momento che viene premuto, rilasciato o digitato un tasto | KeyListener | Component |
MouseEvent | Al momento che un componente viene cliccato, trascinato, o che il cursore entri, esca, o si muova sopra di esso, o che un tasto del mouse venga premuto o rilasciato. | MouseListener
MouseMotionListener |
Component |
WindowEvent | Al momento che una finestra venga iconizzata, deiconizzata, aperta, sia in chiusura o realmente chiusa, attivata o disattivata. | WindowListener | Container |
ActionEvent | Al momento che si verifica un’azione sul componente | ActionListener | Button
List MenuItem TextField |
AdjustmentEvent | Al momento che avvengono variazioni in una ScrollBar. | AdjustmentListener | ScrollBar |
ItemEvent | Al momento in cui cambia lo stato. | ItemListener | Choice
Checkbox CheckboxMenuItem List |
TextEvent | Al momento che cambia un testo. | TextListener | TextArea
TextField |
I gestori di eventi possono essere istanze di qualsiasi classe. Per utilizzare la nuova gestione AWT, bisogna eseguire tre passi:
Se per esempio
abbiamo bisogno di intercettare l’evento di movimento del mouse su un determinato
componente, useremo il metodo mouseMoved(MouseMovedEvent e) dell’interfaccia
MouseMotionListener.
La classe
di ascolto interessata all’evento ridefinirà i metodi necessari
alla gestione dell’evento, e al momento del verificarsi dello stesso, verrà
eseguito il codice incluso in tali metodi. E’ possibile eseguire questa
operazione in due modi. La prima possibilità consiste nell’implementare
direttamente l’interfaccia, per esempio
public class
MiaClasse implements MouseMotionListener {}
In questo modo
la classe eredita tutti i metodi dell’interfaccia MouseMotionListener.
Per esempio
è possibile creare un’applet che faccia da ascoltatore a se stessa.
Utilizzare questo metodo è il modo più semplice per trasformare
un applet scritta con il JDK 1.0.2 in una scritta in JDK 1.1. Tutto ciò
che si deve fare è scrivere un codice del seguente tipo:
public class MiaApplet extends Applet implements MouseMotionListener {...
public void mouseMoved(MouseMotionEvent) {
// codice che verrà eseguito quando avverrà l'evento
...
}
public void mouseDragged(MouseEvent e) {}
}
Come potete
vedere abbiamo dovuto aggiungere anche il metodo mouseDragged()
anche se non ne avevamo bisogno; questa è una regola fissa che si
applica quando viene implementata un’interfaccia, e cioè devono
essere ridefiniti tutti i metodi di quella interfaccia. I metodi che quindi
non servono non conterranno codice. Un altro modo di usare la nuova gestione
è usare quella che viene chiamata adattatore di eventi (classe
adapter), che equivale a creare una classe di ascolto separata dalla
classe originale. Un adattatore è una classe che implementa l’interfaccia
desiderata, e può essere creata direttamente implementando tale
l’interfaccia, o creando una classe che estenda gli adattatori messi a
disposizione nel package java.awt.event. Il vantaggio di estendere
un adattatore già esistente sta nel fatto che si possono usare solo
i metodi che interessano.
Esempio con
uso di implementazione di interfaccia:
class AdattatoreCreatoDaMe implements MouseMotionListener {Esempio di adattatore che estende MouseMotionAdapter classe del package che implementa tutti i metodi dell’interfaccia MouseMotionListener:public void mouseMoved(MouseMotionEvent) {
// codice che verrà eseguito quando avverrà l'evento
...
}
public void mouseDragged(MouseEvent e) {}
}
class AdattatoreCreatoDaMe extends MouseMotionAdapter {Come si può vedere nel secondo caso non c’è stato bisogno di ridefinire il metodo mouseDragged()public void mouseMoved(MouseMotionEvent) {
// codice che verrà eseguito quando avverrà l'evento
...
}
}
L’ultima fase consiste nella registrazione dell’ascoltatore alla lista affinché gli venga notificato l’evento. Questo si fa utilizzando i metodi che troviamo nella classe Component o in una dei suoi figli a secondo la lista scelta (vedere tabella sopra). Questi metodi avranno nome addTipoListener e removeTipoListener per rimuovere la registrazione. Quindi riprendendo l’esempio avremo addMouseMotionListener (MouseMotionListener mml) e removeMouseMotionListener (MouseMotionListener mml). Supponendo che la nostra applet MiaApplet sia interessata al movimento del cursore sul bottone MioBottone scriveremo:
MioBottone.addMouseMotionListener(this);In questo modo avremo registrato l’applet (che implementa l’interfaccia MouseMotionListener) alla appostita lista ascoltatrice.
Clicclando sul
bottone OK viene presentato un frame che la pressione del tasto Notifica
non fa altro che impostare il TextField dell’applet con la dicitura "E'
arrivata la notifica del clic" e nascondersi.
Il codice è
stato scritto usando il JDK 1.0.2., e vedremo come trasformarlo in codice
1.1. Sorgenti in JDK 1.0.2.:
//Codice dell'applet
import java.awt.*;
import java.applet.*;
public class AppletProvaEvento extends Applet {
TextField tNotifica;
Button bOK;
void bOK_Clicked(Event event) {
(new fSorgenteEvento(tNotifica)).show();
}
public void init() {
super.init();
setLayout(null);
addNotify();
resize(280,164);
setBackground(new Color(170));
tNotifica = new TextField();
tNotifica.reshape(24,24,229,38);
tNotifica.setBackground(new Color(16777215));
add(tNotifica);
bOK = new Button("OK");
bOK.reshape(81,96,118,34);
add(bOK);
}
public boolean handleEvent(Event event) {
if (event.target == bOK && event.id == Event.ACTION_EVENT) {
bOK_Clicked(event);
return true;
}
return super.handleEvent(event);
}
}
// Codice del frame
import java.awt.*;
public class fSorgenteEvento extends Frame {
Button bNotifica;
Button bEsci;
label1;
TextField tNotifica;
void bNotifica_Clicked(Event event) {
// qui viene impostato il testo sul TextField dell'applet
tNotifica.setText("E' arrivata la notifica del clic");
hide();
}
void bEsci_Clicked(Event event) {
hide();
}
public fSorgenteEvento(TextField tNotifica) {
this.tNotifica = tNotifica; // carcamento handle del TextField dell'applet
setLayout(null);
addNotify();
resize(insets().left + insets().right + 347,insets().top + insets().bottom + 147);
bNotifica = new Button("Notifica");
bNotifica.reshape(insets().left + 36,insets().top + 96,118,34);
add(bNotifica);
bEsci = new Button("Esci");
bEsci.reshape(insets().left + 204,insets().top + 96,118,34);
add(bEsci);
label1 = new Label("Cliccare su Notifica");
label1.reshape(insets().left + 84,insets().top + 24,171,26);
label1.setFont(new Font("TimesRoman", Font.BOLD, 18));
label1.setForeground(new Color(16711680));
add(label1);
setTitle("Prova Notifica Clic");
}
public fSorgenteEvento(String title, TextField tNotifica) {
this(tNotifica);
setTitle(title);
}
public boolean handleEvent(Event event) {
if (event.id == Event.WINDOW_DESTROY) {
hide();
return true;
}
if (event.target == bEsci && event.id == Event.ACTION_EVENT) {
bEsci_Clicked(event);
return true;
}
if (event.target == bNotifica && event.id == Event.ACTION_EVENT) {
bNotifica_Clicked(event);
return true;
}
return super.handleEvent(event);
}
}
Come potete vedere per intervenire su un componente dell’applet dal frame, è stato necessario passare al frame l’handle di tale componente (tNotifica) creando dei costruttori appositi:
Vediamo ora
come trasformare il tutto in 1.1. Prima di tutto sostituiamo tutti
i metodi DEPRECATED. Quindi:
Cominciamo con il cambiare il codice dell’applet: osservando il programma ci rendiamo conto che l’applet è interessata a due notifiche:
Quindi visto che come evento trattiamo un’azione, le import relative alla nuova gestione:
import java.awt.event.ActionListener;
bOK.addActionListener(this);
sorgente.bNotifica.addActionListener(this);
sorgente.setVisible(true);
Come potete
vedere abbiamo spostato il codice da eseguire dal frame all’applet. Allora
a questo punto non abbiamo più bisogno di passare l’handle del campo
notifica al frame, quindi torniamo ai vecchi costruttori del frame.
Per istanziare avremo:
sorgente
= new fSorgenteEvento();
dove sorgente
è l’istanza di fSorgenteEvento.
Codice finale:
import java.awt.*;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.applet.*;
public class AppletProvaEvento extends Applet implements ActionListener{
TextField tNotifica;
Button bOK;
fSorgenteEvento sorgente;
void bOK_Clicked(ActionEvent event) {
sorgente = new fSorgenteEvento();
sorgente.bNotifica.addActionListener(this);
sorgente.setVisible(true);
}
public void init() {
super.init();
setLayout(null);
addNotify();
setSize(280,164);
setBackground(new Color(170));
tNotifica = new TextField();
tNotifica.setBounds(24,24,229,38);
tNotifica.setBackground(new Color(16777215));
add(tNotifica);
bOK = new Button("OK");
bOK.setBounds(81,96,118,34);
add(bOK);
bOK.addActionListener(this);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == bOK) {
bOK_Clicked(event);
}
else if (event.getSource() == sorgente.bNotifica) {
tNotifica.setText("E' arrivata la notifica del clic");
sorgente.setVisible(false);
}
}
}
Passiamo
a considerare la classe fSorgenteEvento. Dopo aver tolto dai costruttori
il parametro TextField ci accorgiamo di avere due notifiche da gestire,
quella riguardanti il click sul bottone Esci e quella riguardante la chiusura
della finestra (quella del bottone Notifica è intercettato dall’applet).
Questa volta per poter gestire gli eventi utilizzeremo la tecnica della
classe di ascolto separata, cioè quella della creazione di classi
adattatori di eventi. Allora le import relative saranno:
import java.awt.event.WindowEvent;Useremo due tecniche differenti: la prima tecnica la adottiamo per intercettare il click sul bottone Esci; creeremo un’istanza della classe MouseAdapter come Inner Class (classe interna, vedere articolo su Mokabyte di Ottobre 1997 ):import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.WindowAdapter;
// registrazione della classe fSorgenteEvento al click del bottoneCome potete vedere la classe è specializzata sul bottone Esci e anche se avevamo altri bottoni la notifica non sarebbe certo arrivata qui. Questo è un vantaggio nell’adozione degli adapter rispetto all’avere un unico metodo dove gestire tutte le notifiche, come avveniva nell’applet. Nell’applet avevamo avuto bisogno di inserire il costrutto if per poter capire chi era la sorgente dell’evento. La seconda tecnica la usiamo per la chiusura della finestra, consiste nel creare un’estensione della classe adapter che ci interessa (WindowAdapter). Allora avremo la nuova classe:// bEsci
bEsci.addMouseListener(
new MouseAdapter () {
public void mouseClicked(MouseEvent event) {
setVisible(false);
}
});
class MiaWindowAdapter extends WindowAdapter {Il metodo windowClosing gestisce la chiusura della finestra.public void windowClosing(WindowEvent event) {
((Frame)(event.getSource())).setVisible(false);
}
}
A questo punto non rimane che iscrivere questa nuova classe di ascolto:
MiaWindowAdapter WL = new MiaWindowAdapter();
addWindowListener(WL);
Codice finale:
import java.awt.*;Nuovi eventi estensione diretta di EventObject.import java.awt.event.WindowEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.WindowAdapter;
public class fSorgenteEvento extends Frame {
Button bNotifica;
Button bEsci;
Label label1;
public fSorgenteEvento() {
setLayout(null);
addNotify();
setSize(getInsets().left + getInsets().right + 347,getInsets().top + getInsets().bottom + 147);
bNotifica = new Button("Notifica");
bNotifica.setBounds(getInsets().left + 33,getInsets().top + 93,118,34);
add(bNotifica);
bEsci = new Button("Esci");
bEsci.setBounds(getInsets().left + 200,getInsets().top + 92,118,34);
add(bEsci);
label1 = new Label("Cliccare su Notifica");
label1.setBounds(getInsets().left + 84,getInsets().top + 24,171,26);
label1.setFont(new Font("TimesRoman", Font.BOLD, 18));
label1.setForeground(new Color(16711680));
add(label1);
setTitle("Prova Notifica Clic");
bEsci.addMouseListener(
new MouseAdapter () {
public void mouseClicked(MouseEvent event) {
setVisible(false);
}
});
MiaWindowAdapter WL = new MiaWindowAdapter();
addWindowListener(WL);
}
public fSorgenteEvento(String title) {
this();
setTitle(title);
}
}
class MiaWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent event) {
((Frame)(event.getSource())).setVisible(false);
}
}
Questa nuova possibilità viene utilizzata con l'introduzione dei JavaBeans. Gli eventi permettono ad un Bean di comunicare con l'esterno e queste sono le tre parti coinvolte nella comunicazione:
public class EventObject implements java.io.Serializable {Gli eventi gestiti dal bean estenderanno questa classe. Riprendendo l'esempio dell'introduzione, potremmo avere un Bean ConferenzaJava gestore del seguente eventoprotected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
// contiene i metodi che restituiscono le informazioni sull'eventopublic class ProssimaConferenzaJavaEvent extends EventObject {
private java.util.date dateEvent;
private String[] speakers;
private String site;
// Data Evento
public java.util.date getDate() {
return dateEvent
}
// Luogo Evento
public String getSite() {
return site
}
// Nominativi Speaker
public String[] getSpeakers() {
return speakers
}
// altri metodi
...
...
}
L'interfaccia
EventListener è vuota ma serve come interfaccia comune a
tutti gli ascoltatori di eventi che devono estenderla.
Un ascoltatore
è qualcosa che vuole essere notificato quando un evento occorre.
A tutti i metodi dell'interfaccia comune vengono passati come parametri
l'estensione specifica della classe EventObject.
Riprendendo
l'esempio dell'introduzione avremo come interfaccia:
// contiene i metodi che restituiscono le informazioni sull'eventoA questo punto senza una sorgente dell'evento sia ProssimaConferenzaJavaEvent che ProssimaConferenzaJavaListener rimangono non usati. E' la sorgente dell'evento (cioè il bean) che definisce dove e quando un evento avviene. La registrazione (e la cancellazione della registrazione) a questo processo avviene tramite l'uso dei metodipublic interface ProssimaConferenzaJavaListener extends EventListener {
public void prossimaConferenzaJavaPerformed(ProssimaConferenzaJavaEvent e);
}
public synchronized void addTipoListener(TipoListener l)
public synchronized
void removeTipoListener(TipoListener l)
A questo punto
la sorgente dell'evento ha bisogno essa stessa di mantenere la lista per
poterla gestire, così nel caso del nostro esempio il
codice diviene:
private Vector prossimaConferenzaJavaListeners = new Vector();Facendo un paragone con l'AWT, quando si usano i suoi eventi, in questo caso non c'è problema in quanto i due metodi di add e remove sono stati già trattati nella classe Component e quindi basta semplicemente utilizzarli. Per esempio per la lista ascoltatrice ActionListener esistono già i metodi addActionListener() e removeActionListener()
public synchronized void addProssimaConferenzaJavaListener(ProssimaConferenzaJavaListener l) {
prossimaConferenzaJavaListeners.addElement(l);
}
public synchronized void removeProssimaConferenzaJavaListener(ProssimaConferenzaJavaListener l) {
prossimaConferenzaJavaListeners.removeElement(l);
}
protected void notifyProssimaConferenzaJava () {In questo modo vengono invocati tutti i metodi ProssimaConferenzaJavaPerformed definiti in ogni ascoltatore ed eseguito il codice relativo.
Vector l;
// Crea l'evento
ProssimaConferenzaJavaEvent pcj = new ProssimaConferenzaJavaEvent(this)
// Copia gli ascoltatori per evitare che cambino mentre li trattiamo
synchronized (this) {
l = prossimaConferenzaJavaListeners.clone();
}
// Notifica l'evento richiamando tutti i metodi ProssimaConferenzaJavaPerformed
// appartenenti ai vari ascoltatori.
for (int i=0;i<l.size();i++) {
ProssimaConferenzaJavaListener pcjl = (ProssimaConferenzaJavaListener)l.elementAt(i);
pcjl.ProssimaConferenzaJavaPerformed(pcj);
}
}
Conclusione.
Spero che questo
articolo sia stato utile nella comprensione di questa elegante e organizzata
nuova gestione degli eventi, a quanti stanno cercando di affrontare il
JDK 1.1. per la prima volta.
|
||
MokaByte ricerca
nuovi collaboratori.
|
||
|