22. Gestire gli Eventi
ActionScript 3 come il suo predecessore supporta la gestione degli eventi, intendendo questi ultimi come avvenimenti che si verificano nell'applicazione, come la pressione di un tasto, un clic del mouse, l'avvenuto scaricamento di una foto e così via.
Per poter fornire una risposta a questi eventi, è necessario poter capire quando si verificano e fornire di conseguenza una funzione da eseguire in tale caso, ed è qui che vengono in nostro aiuto i listener.
I listener sono delle funzioni (o metodi) che rimangono in "ascolto" attendendo il verificarsi di un determinato evento, per poi procedere di conseguenza nel caso in cui si verificasse.
In ActionScript 3, l'unico modo per aggiungere un listener ad un oggetto, è tramite il metodo addEventListener che richiameremo dall'oggetto interessato fornendogli due parametri :
- Evento specifico per cui rimanere in ascolto
- Funzione o metodo di risposta da eseguire al verificarsi dell'evento
Nell'esempio che segue utilizzerò la classe documento HelloWorld a cui aggiungerò un listener, che rimarrà in ascolto per i click del mouse effettuati sullo stage del filmato :
package
{
import flash.display.MovieClip;
public class HelloWorld extends MovieClip
{
public function HelloWorld():void
{
stage.addEventListener("click", clickHandler);
}
private function clickHandler(evento:*):void
{
trace("Hai cliccato sullo stage!");
}
}
}Il filmato prodotto dal codice soprastante, traccerà la frase "Hai cliccato sullo stage!" nel pannello Output ogni volta che cliccheremo sullo stage. Prima di procedere apportiamo qualche modifica al codice, usando una costante invece di una stringa per indicare il tipo di evento da controllare ("click"), così se commettiamo un errore di ortografia il compilatore potrà assisterci segnalandoci l'errore, mentre se sbagliamo a scrivere il tipo di evento sotto forma di stringa, l'errore non ci verrebbe segnalato. Il metodo che sto per illustrare è utile anche per via dei suggerimenti che Flash ci propone durante la scrittura del codice, constatando in tempo reale per quali eventi possiamo effettivamente metterci in ascolto. |
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class HelloWorld extends MovieClip
{
public function HelloWorld():void
{
// Usiamo la costante CLICK della classe "MouseEvent" piuttosto della stringa "click"
stage.addEventListener(MouseEvent.CLICK, clickHandler);
}
// "evento" non sarà più di tipo non definito ma un'istanza della classe "MouseEvent"
private function clickHandler(evento:MouseEvent):void
{
trace("Hai cliccato sullo stage!");
}
}
}Nell'esempio soprastante ho dichiarato un metodo "clickHandler" da utilizzare come risposta all'evento, ma potrebbe tornarvi utile sapere che ActionScript ci consente di utilizzare anche le funzioni globali per lo stesso scopo.
Da notare anche che ho richiamato il metodo addEventListener dall'oggetto speciale stage, ma se ad esempio avessi dovuto catturare la pressione di un tasto per un campo di testo, lo avrei richiamato da quest ultimo, ossia il destinatario dell'evento.
Eventi personalizzati
Un altra caratteristica molto importante di ActionScript 3, è la possibilità di creare ed inviare degli eventi personalizzati per gestire in maniera ancora più completa le nostre classi, che attraverso l'ereditarietà della classe EventDispatcher potranno fornirci uno strumento molto potente per la costruzione di complesse applicazioni web.
Per capire meglio ho costruito un semplice esempio realizzando una classe "Tracer", che data una stringa nè traccerà in Output una lettera ogni N millisecondi fino al completamento della stringa, momento in cui invierà un evento personalizzato rappresentato dalla classe "TracerEvent".
Iniziamo con la costruzione della classe TracerEvent che fungerà da enumerazione per le costanti d'evento.
TracerEvent.as
package
{
public final class TracerEvent
{
public static const TRACE_STARTED:String = "TraceStarted";
public static const TRACE_COMPLETE:String = "TraceComplete";
}
}Per questo esempio ho creato solo queste due costanti per rappresentare l'inizio della tracciatura della parola (TraceStarted) e la fine della tracciatura (TraceComplete), puramente a scopo didattico e dimostrativo.
Prima di procedere con la scrittura della classe Tracer che sarà derivata da EventDispatcher, daremo un'occhiata a quest'ultima, analizzandone velocemente i metodi.
EventDispatcher
- addEventListener - consente di aggiungere un listener all'oggetto per ricevere la notifica di un evento specifico
- dispatchEvent - invia un evento (un istanza della classe Event o una sua derivata)
- hasEventListener - controlla l'esistenza di un listener sull'oggetto per un determinato evento
- removeEventListener - consente di rimuovere un listener dall'oggetto
- willTrigger - controlla se un listener è registrato a questo oggetto o ad un suo antenato
Tracer.as
package
{
import TracerEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
public class Tracer extends EventDispatcher
{
// Stringa da tracciare
private var text:String;
// Oggetto "Timer" utilizzato per tracciare una lettera ogni N millisecondi
private var counter:Timer;
// Intervallo per stabilire ogni quanti millisecondi va tracciata una lettera
private var interval:Number;
public function Tracer(newText:String, newInterval:Number = 100):void
{
this.text = newText;
this.interval = newInterval;
}
public function start():void
{
this.counter = new Timer(this.interval, this.text.length);
/* Aggiungo un listener per richiamare "timerHandler" ogni volta
che passa il numero di millisecondi stabiliti come intervallo
Nota : non ha a che fare con i nostri eventi personalizzati */
this.counter.addEventListener(TimerEvent.TIMER, timerHandler);
this.counter.start();
// Invio l'evento TRACE_STARTED nel flusso di eventi
super.dispatchEvent(new Event(TracerEvent.TRACE_STARTED));
}
private function timerHandler(event:TimerEvent):void
{
trace(this.text.charAt(this.counter.currentCount - 1));
if (this.text.length == this.counter.currentCount)
{
// Invio l'evento TRACE_COMPLETE nel flusso di eventi
super.dispatchEvent(new Event(TracerEvent.TRACE_COMPLETE));
}
}
}
}A questo punto la nostra libreria è completa e non ci rimane che testarla attraverso la classe HelloWorld :
package
{
import Tracer;
import TracerEvent;
import flash.events.Event;
import flash.display.MovieClip;
public class HelloWorld extends MovieClip
{
public function HelloWorld():void
{
var myTracer:Tracer = new Tracer("Ciao", 500);
myTracer.addEventListener(TracerEvent.TRACE_STARTED, traceHandler);
myTracer.addEventListener(TracerEvent.TRACE_COMPLETE, traceHandler);
myTracer.start();
}
private function traceHandler(evento:Event):void
{
if (evento.type == TracerEvent.TRACE_STARTED)
trace("Inizio tracciatura!");
else if (evento.type == TracerEvent.TRACE_COMPLETE)
trace("Tracciatura completata!");
else
trace("Errore, evento non riconosciuto!");
}
}
}L'esempio soprastante produce il seguente output : |
Nota : I metodi della classe EventDispatcher (es. addEventListener) non sono ridefinibili (override), tuttavia esiste la possibilità di apportarvi delle modifiche attraverso l'implementazione dell'interfaccia IEventDispatcher, usando poi un attributo di tipo EventDispatcher per aggiungere effettivamente i listener, inviare eventi eccetera ...
Tracer.as
package
{
import TracerEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
// Nota che non eredita più da EventDispatcher ma implementa IEventDispatcher
public class Tracer implements IEventDispatcher
{
private var dispatcher:EventDispatcher;
// ...
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
{
// ... modifiche varie
this.dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
// ...
}
}- Linguaggi:
- Tags:
