Evento di gestione eventi: Alarm Clock

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

L'esempio Alarm Clock rappresenta un orologio che permette all'utente di specificare l'ora in cui si deve attivare la sveglia e il messaggio da visualizzare in quel momento. Questo esempio si basa sull'applicazione SimpleClock, disponibile in Operazioni con data e ora e illustra vari aspetti dell'uso di eventi in ActionScript 3.0, tra cui:

  • Ascolto e risposta a un evento

  • Notifica dei listener di un evento

  • Creazione di un tipo di evento personalizzato

Per ottenere i file dell'applicazione Flash Professional per questo esempio, vedete http://www.adobe.com/go/learn_programmingAS3samples_flash_it . Per ottenere i file dell'applicazione Flex per questo esempio, vedete http://www.adobe.com/go/learn_as3_usingexamples_it . I file dell'applicazione Alarm Clock si trovano nella cartella Samples/AlarmClock. L'applicazione comprende i file seguenti:

File

Descrizione

AlarmClockApp.mxml

o

AlarmClockApp.fla

Il file principale dell'applicazione in Flash (FLA) o Flex (MXML)

com/example/programmingas3/clock/AlarmClock.as

Classe che estende la classe SimpleClock aggiungendo la funzionalità sveglia.

com/example/programmingas3/clock/AlarmEvent.as

Classe evento personalizzata (sottoclasse di flash.events.Event) che funge da oggetto evento per l'evento alarm della classe AlarmClock.

com/example/programmingas3/clock/AnalogClockFace.as

Disegna un orologio rotondo con lancette per le ore, i minuti e i secondi (descritto nell'esempio SimpleClock).

com/example/programmingas3/clock/SimpleClock.as

Componente di interfaccia clock con funzionalità di misurazione del tempo semplice (descritta nell'esempio SimpleClock).

Panoramica di Alarm Clock

Per assolvere alla funzionalità principale dell'orologio di questo esempio, cioè misurare il tempo e visualizzare il quadrante, viene riutilizzato il codice dell'applicazione SimpleClock, descritto in Esempio di data e ora: un semplice orologio analogico . La classe AlarmClock estende la classe SimpleClock aggiungendo la funzionalità sveglia, che permette di impostare l'ora in cui si deve attivare la sveglia e inviare una notifica quando la sveglia “suona”.

Fornire una notifica per indicare che avviene qualcosa è il compito per cui sono stati inventati gli eventi. La classe AlarmClock espone l'evento Alarm, che altri oggetti possono ascoltare al fine di eseguire le azioni desiderate. Inoltre, la classe AlarmClock usa un'istanza della classe Timer per determinare quando la sveglia deve essere attivata. Analogamente alla classe AlarmClock, la classe Timer genera un evento per avvertire altri oggetti (un'istanza di AlarmClock, in questo caso) quando è trascorsa una determinata quantità di tempo. Come per la maggior parte delle applicazioni ActionScript, gli eventi rappresentano un componente importante della funzionalità dell'applicazione di esempio Alarm Clock.

Attivazione della sveglia

Come accennato in precedenza, l'unica funzionalità a cui presiede la classe AlarmClock è l'impostazione e l'attivazione della sveglia. La classe incorporata Timer (flash.utils.Timer) rappresenta per lo sviluppatore un modo per definire il codice che deve essere eseguito una volta trascorsa la quantità di tempo specificata. La classe AlarmClock usa un'istanza di Timer per determinare quando la sveglia deve essere attivata.

    import flash.events.TimerEvent; 
    import flash.utils.Timer; 
 
    /** 
     * The Timer that will be used for the alarm. 
     */ 
    public var alarmTimer:Timer; 
    ... 
    /** 
     * Instantiates a new AlarmClock of a given size. 
     */ 
    public override function initClock(faceSize:Number = 200):void 
    { 
        super.initClock(faceSize); 
        alarmTimer = new Timer(0, 1); 
        alarmTimer.addEventListener(TimerEvent.TIMER, onAlarm); 
    }

L'istanza di Timer definita nella classe AlarmClock è denominata alarmTimer . Il metodo initClock() , che esegue operazioni di configurazione necessarie per l'istanza di AlarmClock, esegue due operazioni con la variabile alarmTimer . Innanzi tutto, viene creata un'istanza della variabile con parametri che indicano all'istanza di Timer di attendere 0 millisecondi e di attivare l'evento timer una sola volta. Dopo la creazione dell'istanza di alarmTimer , il codice chiama il metodo addEventListener() della variabile per indicare che deve ascoltare l'evento timer della variabile. Le istanze Timer inviano il proprio evento timer una volta trascorsa la quantità di tempo predefinita. Per poter attivare la sveglia, la classe AlarmClock deve sapere quando l'evento timer viene inviato. Chiamando addEventListener() , il codice AlarmClock si registra come listener in alarmTimer . I due parametri indicano che la classe AlarmClock ascolta l'evento timer (indicato dalla costante TimerEvent.TIMER ) e quando l'evento si verifica, il metodo onAlarm() della classe AlarmClock deve essere chiamato in risposta all'evento.

Per eseguire l'impostazione della sveglia, viene chiamato il metodo setAlarm() della classe AlarmClock nel modo seguente:

    /** 
     * Sets the time at which the alarm should go off. 
     * @param hour The hour portion of the alarm time. 
     * @param minutes The minutes portion of the alarm time. 
     * @param message The message to display when the alarm goes off. 
     * @return The time at which the alarm will go off. 
     */ 
    public function setAlarm(hour:Number = 0, minutes:Number = 0, message:String = "Alarm!"):Date 
    { 
        this.alarmMessage = message; 
        var now:Date = new Date(); 
        // Create this time on today's date. 
        alarmTime = new Date(now.fullYear, now.month, now.date, hour, minutes); 
 
        // Determine if the specified time has already passed today. 
        if (alarmTime <= now) 
        { 
            alarmTime.setTime(alarmTime.time + MILLISECONDS_PER_DAY); 
        } 
     
        // Stop the alarm timer if it's currently set. 
        alarmTimer.reset(); 
        // Calculate how many milliseconds should pass before the alarm should 
        // go off (the difference between the alarm time and now) and set that 
        // value as the delay for the alarm timer. 
        alarmTimer.delay = Math.max(1000, alarmTime.time - now.time); 
        alarmTimer.start(); 
     
        return alarmTime; 
    }

Questo metodo esegue varie attività, compresa la registrazione del messaggio di sveglia e la creazione di un oggetto Date ( alarmTime ) che rappresenta il momento preciso in cui la sveglia si attiva. Di particolare rilevanza per questa discussione sono le ultime righe del metodo, la modalità in cui il timer della variabile alarmTimer viene impostato e attivato. Per cominciare, viene chiamato il metodo reset() che arresta il timer e lo azzera nel caso fosse già in esecuzione. In seguito, l'ora attuale (rappresentata dalla variabile now ) viene sottratta dal valore della variabile alarmTime per determinare quanti millisecondi devono trascorrere prima che la sveglia si attivi. La classe Timer non attiva il suo evento timer a un'ora assoluta, quindi è la differenza oraria relativa che viene assegnata alla proprietà delay di alarmTimer . Infine, viene chiamato il metodo start() per avviare il timer.

Una volta trascorsa la quantità di tempo specificata, alarmTimer invia l'evento timer . Poiché la classe AlarmClock ha registrato il suo metodo onAlarm() come listener di quell'evento, quando si verifica l'evento timer , viene chiamato onAlarm() .

    /** 
     * Called when the timer event is dispatched. 
     */ 
    public function onAlarm(event:TimerEvent):void  
    { 
        trace("Alarm!"); 
        var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); 
        this.dispatchEvent(alarm); 
    }

Un metodo registrato come listener di eventi deve essere definito con l'indicatore appropriato (cioè, l'insieme di parametri e il tipo restituito del metodo). Per poter essere impostato come listener dell'evento timer della classe Timer, un metodo deve definire un parametro il cui tipo di dati è TimerEvent (flash.events.TimerEvent), una sottoclasse della classe Event. Quando l'istanza di Timer chiama i propri listener di eventi, passa un'istanza di TimerEvent come oggetto evento.

Invio di notifiche per l'evento alarm

Come la classe Timer, la classe AlarmClock fornisce un evento che permette ad altre porzioni di codice di ricevere notifiche dell'attivazione della sveglia. Per poter usare la struttura di gestione degli eventi incorporata nel linguaggio ActionScript, una classe deve implementare l'interfaccia flash.events.IEventDispatcher. Ciò avviene, comunemente, estendendo la classe flash.events.EventDispatcher, che fornisce un'implementazione standard di IEventDispatcher (o tramite l'estensione di una delle sottoclassi di EventDispatcher). Come descritto in precedenza, la classe AlarmClock estende la classe SimpleClock, che (attraverso una catena di ereditarietà) estende la classe EventDispatcher. Questo significa che la classe AlarmClock è già intrinsecamente dotata della funzionalità necessaria alla generazione dei propri eventi.

Altre porzioni di codice possono essere registrate come destinatarie delle notifiche dell'evento alarm della classe AlarmClock chiamando il metodo addEventListener() che AlarmClock eredita da EventDispatcher. Quando è pronta per comunicare ad altre porzioni di codice che il suo evento alarm si è verificato, un'istanza di AlarmClock chiama il metodo dispatchEvent() , anch'esso ereditato da EventDispatcher.

        var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); 
        this.dispatchEvent(alarm);

Le seguenti righe di codice sono state estratte dal metodo onAlarm() della classe AlarmClock (riprodotto integralmente in precedenza). Viene chiamato il metodo dispatchEvent() dell'istanza AlarmClock, che notifica tutti i listener registrati che l'evento alarm dell'istanza di AlarmClock è stato attivato. Il parametro passato a dispatchEvent() è l'oggetto evento che viene trasmesso ai metodi del listener. In questo caso, si tratta di un'istanza della classe AlarmEvent, una sottoclasse di Event creata specificamente per questo esempio.

Creazione di un evento alarm personalizzato

Tutti i listener di eventi ricevono un parametro dell'oggetto evento che indica il particolare tipo di evento attivato. In molti casi, l'oggetto evento è un'istanza della classe Event. Tuttavia, talvolta, è opportuno fornire informazioni supplementari ai listener. Il modo più comune per svolgere questa operazione consiste nel definire una nuova classe (una sottoclasse della classe Event) e di usare una sua istanza come oggetto evento. In questo esempio, un'istanza di AlarmEvent viene usata come oggetto evento quando l'evento alarm della classe AlarmClock viene inviato. La classe AlarmEvent, riportata di seguito, fornisce informazioni supplementari sull'evento alarm , in particolare il messaggio di avvertenza:

    import flash.events.Event; 
     
    /** 
     * This custom Event class adds a message property to a basic Event. 
     */ 
    public class AlarmEvent extends Event  
    { 
        /** 
         * The name of the new AlarmEvent type. 
         */ 
        public static const ALARM:String = "alarm"; 
         
        /** 
         * A text message that can be passed to an event handler 
         * with this event object. 
         */ 
        public var message:String; 
         
        /** 
         *Constructor. 
         *@param message The text to display when the alarm goes off. 
         */ 
        public function AlarmEvent(message:String = "ALARM!") 
        { 
            super(ALARM); 
            this.message = message; 
        } 
        ... 
    }

Il modo migliore per creare una classe oggetto evento personalizzata consiste nel definire una classe che estende la classe Event, come illustrato nell'esempio precedente. Per completare la funzionalità ereditata la classe AlarmEvent definisce la proprietà message che contiene il testo del messaggio associato all'evento; il valore message viene passato come parametro nella funzione di costruzione AlarmEvent. La classe AlarmEvent definisce anche la costante ALARM , che può essere usata come riferimento all'evento specifico ( alarm ) quando si chiama il metodo addEventListener() della classe AlarmClock.

Oltre ad aggiungere delle funzionalità personalizzate, ogni sottoclasse di Event deve sostituire il metodo clone() ereditato come parte della struttura di gestione degli eventi di ActionScript. In via facoltativa, le sottoclassi di Event possono anche sostituire il metodo ereditato toString() al fine di includere le proprietà dell'evento personalizzato nel valore restituito quanto il metodo toString() viene chiamato.

    /** 
     * Creates and returns a copy of the current instance. 
     * @return A copy of the current instance. 
     */ 
    public override function clone():Event 
    { 
        return new AlarmEvent(message); 
    } 
     
    /** 
     * Returns a String containing all the properties of the current 
     * instance. 
     * @return A string representation of the current instance. 
     */ 
    public override function toString():String 
    { 
        return formatToString("AlarmEvent", "type", "bubbles", "cancelable", "eventPhase", "message"); 
    }

Il metodo sostituito clone() deve restituire una nuova istanza della sottoclasse Event personalizzata con tutte le proprietà personalizzate impostate sull'istanza corrente. Nel metodo sostituito toString() , il metodo utilità formatToString() (ereditato da Event) viene usato per fornire una stringa con il nome del tipo personalizzato e i nomi e i valori di tutte le sue proprietà.