Przykład obsługi zdarzeń: Alarm Clock

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

W przykładzie Alarm Clock przedstawiono zegar, który umożliwia określenie czasu, w którym zostanie uruchomiony alarm, a także zawiera komunikat, który będzie wyświetlany w przed uruchomieniem alarmu. W przykładzie Alarm Clock wykorzystano aplikację SimpleClock z sekcji Praca z datami i czasem . Przykład Alarm Clock ilustruje kilka aspektów pracy ze zdarzeniami w języku ActionScript 3.0, między innymi:

  • Wykrywanie zdarzeń i reagowanie na nie

  • Powiadamianie użytkowników o zdarzeniach

  • Tworzenie niestandardowych typów zdarzeń

Aby pobrać pliki tej przykładowej aplikacji w wersji dla programu Flash Professional, należy skorzystać ze strony http://www.adobe.com/go/learn_programmingAS3samples_flash_pl . Aby pobrać pliki tej przykładowej aplikacji w wersji dla środowiska Flex, należy skorzystać ze strony http://www.adobe.com/go/as3examples_pl . Pliki aplikacji Alarm Clock są dostępne w folderze Samples/AlarmClock. Aplikacja obejmuje następujące pliki:

File

Opis

AlarmClockApp.mxml

lub

AlarmClockApp.fla

Główny plik aplikacji w formacie Flash (FLA) lub Flex (MXML).

com/example/programmingas3/clock/AlarmClock.as

Klasa, która stanowi rozszerzenie klasy SimpleClock — dodaje funkcję alarmu.

com/example/programmingas3/clock/AlarmEvent.as

Niestandardowa klasa zdarzeń (podklasa klasy flash.events.Event), która jest wykorzystywana jako obiekt zdarzenia dla zdarzenia alarm klasy AlarmClock.

com/example/programmingas3/clock/AnalogClockFace.as

Rysuje okrągłą tarczę zegara, a także wskazówki: godzinową, minutową i sekundową (opisane w przykładzie SimpleClock).

com/example/programmingas3/clock/SimpleClock.as

Składnik interfejsu zegara z prostą funkcją kontroli czasu (opisane w przykładzie SimpleClock).

Alarm Clock — przegląd

Główna funkcja zegara w tym przykładzie, oprócz śledzenia czasu i wyświetlania tarczy zegara, korzysta ponownie z kodu aplikacji SimpleClock, która została opisana w rozdziale Przykład z datą i godziną: prosty zegar analogowy . Klasa AlarmClock stanowi rozszerzenie klasy SimpleClock z przykładu — dodaje funkcje wymagane dla budzika, między innymi: funkcję ustawiania czasu alarmu i powiadamiania o uruchomieniu alarmu.

Powiadomienie to najważniejsza funkcja zdarzeń. Klasa AlarmClock udostępnia zdarzenie Alarm, które może być wykrywane przez inne obiekty w celu wykonywania żądanych operacji. Ponadto klasa AlarmClock korzysta z instancji klasy Timer w celu określenia czasu wywoływania alarmu. Klasa Timer — podobnie, jak klasa AlarmClock — udostępnia zdarzenie, które powiadamia inne obiekty (w tym przypadku instancja AlarmClock) o upływie określonego czasu. Zdarzenia — podobnie jak w większości aplikacji ActionScript — stanowią istotną część funkcji przykładowej aplikacji Alarm Clock.

Uruchamianie alarmu

Jak wspomniano powyżej — jedyna funkcja, którą udostępnia aplikacja AlarmClock, odwołuje się do ustawiania i uruchamiania alarmu. Wbudowana klasa Timer (flash.utils.Timer) umożliwia programiście napisanie kodu, który zostanie wykonany po upływie określonego czasu. Klasa AlarmClock korzysta z instancji Timer w celu określenia czasu uruchomienia alarmu.

    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); 
    }

Instancja Timer zdefiniowana w klasie AlarmClock ma nazwę alarmTimer . Metoda initClock() , która wykonuje niezbędne operacje ustawiania dla instancji AlarmClock, wykonuje dwie czynności ze zmienną alarmTimer . Po pierwsze: zmienna zostaje zainicjowana z parametrami, które stanowią dla instancji Timer instrukcję oczekiwania przez czas 0 milisekund oraz instrukcję uruchomienia zdarzenia Timer tylko jeden raz. Po wywołaniu alarmTimer kod wywołuje metodę addEventListener() zmiennej, co oznacza, że chce wykryć zdarzenie timer zmiennej. Instancja Timer działa poprzez wywoływanie jej zdarzenia timer nawet po upływie określonego czasu. Klasa AlarmClock musi wiedzieć o wywołaniu zdarzenia timer w celu uruchomienia własnego alarmu. Wywołując metodę addEventListener() kod aplikacji AlarmClock rejestruje się jako detektor w alarmTimer . Te dwa parametry oznaczają, że klasa AlarmClock chce wykrywać zdarzenie timer (na co wskazuje zmienna TimerEvent.TIMER ), oraz że w odpowiedzi na zdarzenie powinna zostać wywołana metoda onAlarm() klasy AlarmClock.

W celu ustawienia alarmu wywoływana jest metoda setAlarm() klasy AlarmClock:

    /** 
     * 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; 
    }

Ta metoda wykonuje kilka operacji, między innymi: zapisuje komunikat alarmu i tworzy obiekt Date ( alarmTime ), który reprezentuje rzeczywisty moment, w którym nastąpi uruchomienie alarmu. Najważniejsze w tym opisie jest to, że w kilku ostatnich liniach metody następuje ustawienie i aktywacja zmiennej alarmTimer licznika czasu. Najpierw następuje wywołanie metody reset() , która zatrzymuje licznik czasu, jeśli licznik działa. Następnie bieżący czas (reprezentowany przez zmienną now ) jest odejmowany od wartości zmiennej alarmTime w celu określenia liczby milisekund, jaka upłynie przed uruchomieniem alarmu. Klasa Timer nie wywołuje jej zdarzenia timer w czasie bezwzględnym, więc do właściwości delay zmiennej alarmTimer zostaje przypisana względna różnica czasu. Ostatecznie wywoływana jest metoda start() , która uruchamia licznik czasu.

Po upływie określonego czasu zmienna alarmTimer wywołuje zdarzenie timer . Klasa AlarmClock zarejestrowała metodę onAlarm() jako detektor dla tego zdarzenia, dlatego po zdarzeniu timer wywoływana jest metoda 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); 
    }

Metoda, która została zarejestrowana jako detektor zdarzenia, musi zostać zdefiniowana z odpowiednim podpisem (tj. z zestawem parametrów i typem powrotu metody). Aby metoda była detektorem zdarzenia timer klasy Timer, metoda musi definiować jeden parametr, który zawiera dane typu TimerEvent (flash.events.TimerEvent) — jest to podklasa klasy Event. Gdy instancja Timer wywoła swoje detektory zdarzeń, przekaże instancję TimerEvent jako obiekt zdarzenia.

Powiadamianie innych o alarmie

Klasa AlarmClock — podobnie jak klasa Timer — udostępnia zdarzenie, dzięki któremu inny kod może otrzymać powiadomienie o uruchomieniu alarmu. Aby klasa mogła korzystać ze struktury obsługi zdarzeń wbudowanej do języka ActionScript, klasa musi implementować interfejs flash.events.IEventDispatcher. Jest to możliwe, gdy klasa flash.events.EventDispatcher zostanie rozszerzona — w wyniku rozszerzenia następuje udostępnienie standardowej implementacji IEventDispatcher (lub poprzez rozszerzenie jednej z podklas klasy EventDispatcher). Jak już wcześniej wspomniano, klasa AlarmClock rozszerza klasę SimpleClock, która (poprzez łańcuch dziedziczenia) rozszerza klasę EventDispatcher. Oznacza to, że klasa AlarmClock zawiera wbudowane funkcje, dzięki którym może udostępniać swoje własne zdarzenia.

Inny kod może być powiadamiany o zdarzeniu alarm klasy AlarmClock, gdy wywoła metodę addEventListener() , którą klasa AlarmClock dziedziczy z klasy EventDispatcher. Gdy instancja AlarmClock jest gotowa do powiadomienia innego kodu o wystąpieniu zdarzenia alarm , powiadamia poprzez wywołanie metody dispatchEvent() , która również jest dziedziczona z klasy EventDispatcher.

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

Te wiersze klasy pochodzą z metody onAlarm() klasy AlarmClock (poprzednio zaprezentowano całą metodę). Następuje wywołanie metody dispatchEvent() klasy AlarmClock, która powiadamia wszystkie zarejestrowane detektory o wywołaniu zdarzenia alarm instancji AlarmClock. Parametr przekazany do dispatchEvent() jest obiektem zdarzenia, który zostanie przekazany również do metod detektora. W takim przypadku jest on instancją klasy AlarmEvent, która jest podklasą klasy Event utworzoną specjalnie w tym przykładzie.

Udostępnianie niestandardowego zdarzenia alarmu

Wszystkie detektory zdarzeń odbierają parametr obiektu zdarzenia z informacją o wywołaniu konkretnego zdarzenia. W wielu przypadkach obiekt zdarzenia jest instancją klasy Event. Jednak w niektórych przypadkach lepszym rozwiązaniem jest udostępnienie dodatkowych informacji do detektorów zdarzeń. Często stosowanym sposobem osiągnięcia tego celu jest zdefiniowanie nowej klasy, podklasy klasy Event, a następnie użycie instancji tej klasy jako obiektu zdarzenia. W tym przykładzie instancja AlarmEvent jest używana jako obiekt zdarzenia przy wywołaniu zdarzenia alarm klasy AlarmClock. Przedstawiona klasa AlarmEvent udostępnia dodatkowe informacje o zdarzeniu alarm , przede wszystkim komunikat alarmu:

    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; 
        } 
        ... 
    }

Najlepszym sposobem na utworzenie niestandardowego obiektu zdarzenia jest zdefiniowanie klasy, która rozszerzy klasę Event, co przedstawiono w poprzednim przykładzie. W celu uzupełnienia odziedziczonej funkcji w klasie AlarmEvent zdefiniowano właściwość message , która zawiera tekst komunikatu alarmu skojarzony z danym zdarzeniem; wartość message jest przekazywana jako parametr do konstruktora AlarmEvent. Klasa AlarmEvent definiuje również stałą ALARM , która może służyć jako odwołanie do określonego zdarzenia ( alarm ) podczas wywołania metody addEventListener() klasy AlarmClock.

Oprócz dodawania funkcji niestandardowych każda podklasa Event musi zastępować odziedziczoną metodę clone() jako część ActionScript event-handling framework. Podklasy klasy Event mogą również opcjonalnie zastępować odziedziczoną metodę toString() w celu uwzględniania niestandardowych właściwości zdarzenia w wartości zwracanej po wywołaniu metody toString() .

    /** 
     * 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"); 
    }

Zastąpiona metoda clone() musi zwracać nową instancję niestandardowej podklasy Event z wszystkimi niestandardowymi właściwościami ustawionymi w taki sposób, aby były zgodne z bieżącą instancją. W zastąpionej metodzie toString() metoda narzędziowa formatToString() (odziedziczona z Event) udostępnia ciąg z nazwą niestandardowego typu, a także nazwy i wartości wszystkich jego właściwości.