範例:鬧鐘

「鬧鐘」範例包含可讓使用者指定響鈴時間的時鐘,以及要在該時間顯示的訊息。「鬧鐘」範例是根據使用日期與時間.的 SimpleClock 應用程式所建置,它會說明在 ActionScript 3.0 中處理事件的數項觀點,其中包括:

若要取得此樣本的應用程式檔案,請參閱 www.adobe.com/go/learn_programmingAS3samples_flash_tw。您可以在 Samples/AlarmClock 檔案夾中找到「鬧鐘」應用程式檔案。這個應用程式包含下列檔案:

檔案

說明

AlarmClockApp.mxml

AlarmClockApp.fla

Flash (FLA) 或 Flex (MXML) 中的主應用程式檔案。

com/example/programmingas3/clock/AlarmClock.as

會擴充 SimpleClock 類別的類別,以增加鬧鐘的功能。

com/example/programmingas3/clock/AlarmEvent.as

自訂的事件類別 (flash.events.Event 的子類別),當做 AlarmClock 類別之 alarm 事件的事件物件來使用。

com/example/programmingas3/clock/AnalogClockFace.as

繪製圓形時鐘外觀,並根據時間繪製時針、分針和秒針 (已在 SimpleClock 範例中加以說明)。

com/example/programmingas3/clock/SimpleClock.as

具有簡單計時功能的時鐘介面組件 (已在 SimpleClock 範例中加以說明)。

副主題

鬧鐘概觀
觸發響鈴
通知其它偵聽程式有關此響鈴事件
提供自訂的 alarm 事件

鬧鐘概觀

本範例中鬧鐘的主要功能 (包含追蹤時間及顯示鬧鐘外觀) 會重複使用 SimpleClock 應用程式程式碼,這已在範例:簡單的類比時鐘中加以說明。AlarmClock 類別會從該範例中,藉由加入鬧鐘所需的功能來擴充 SimpleClock 類別,這些功能包括設定響鈴時間,以及當響鈴響起時提供通知。

建立事件的原因,就是為了工作中有事發生時能夠提供通知。AlarmClock class 會公開 Alarm 事件,為了執行所需的動作,其它物件都可以偵聽此事件。此外,AlarmClock 類別還會使用 Timer 類別的實體,以判斷何時要觸發它的響鈴。與 AlarmClock 類別相似,Timer 類別也可以在經過特定時間之後,提供事件來通知其它物件 (在此範例中,則為 AlarmClock 實體)。和大多數 ActionScript 應用程式一樣,事件構成了「鬧鐘」樣本應用程式的一部分重要功能。

觸發響鈴

如先前內容所提及,AlarmClock 類別實際提供的唯一功能會與設定和觸發響鈴有關。內建的 Timer 類別 (flash.utils.Timer) 可提供一種方式,讓開發人員定義在指定的時間量之後執行的程式碼。AlarmClock 類別會使用 Timer 實體,判斷何時要觸發響鈴。

    import flash.events.TimerEvent;
    import flash.utils.Timer;

    /**
     * 要用於響鈴的 Timer。
     */
    public var alarmTimer:Timer;
    ...
    /**
     * 以指定的大小實體化新的 AlarmClock。
     */
    public override function initClock(faceSize:Number = 200):void
    {
        super.initClock(faceSize);
        alarmTimer = new Timer(0, 1);
        alarmTimer.addEventListener(TimerEvent.TIMER, onAlarm);
    }

在 AlarmClock 類別中定義的 Timer 實體名為 alarmTimerinitClock() 方法 (會執行 AlarmClock 實體所需的設定作業) 會以 alarmTimer 變數執行兩件事。首先,它會搭配參數 (指示 Timer 實體等待 0 毫秒) 以實體化該變數,並且只觸發其 timer 事件一次。實體化 alarmTimer 之後,程式碼便會呼叫該變數的 addEventListener() 方法,表示它要偵聽該變數的 timer 事件。在經過指定的時間量之後,藉由傳送 Timer 實體的 timer 事件,讓此實體得以運作。AlarmClock 類別必須知道傳送 timer 事件的時間,以便觸發它自己的響鈴。藉由呼叫 addEventListener(),AlarmClock 程式碼便可以使用 alarmTimer 將本身註冊為偵聽程式。這兩個參數表示 AlarmClock 類別要偵聽 timer 事件 (由 TimerEvent.TIMER 常數所表示),以及當事件發生時,要呼叫 AlarmClock 類別的 onAlarm() 方法來回應該事件。

為了要實際設定響鈴,會呼叫 AlarmClock 類別的 setAlarm() 方法,如下所示:

    /**
     * 設定響鈴要響起的時間。
     * @param hour 響鈴時間的小時部分。
     * @param minutes 響鈴時間的分鐘部分。
     * @param message 響鈴響起時要顯示的訊息。
     * @return 響鈴要響起的時間。
     */
    public function setAlarm(hour:Number = 0, minutes:Number = 0, message:String = "Alarm!"):Date
    {
        this.alarmMessage = message;
        var now:Date = new Date();
        // 以今天的日期來建立 this 時間。
        alarmTime = new Date(now.fullYear, now.month, now.date, hour, minutes);

        // 判斷指定的時間是否已經過了今天。
        if (alarmTime <= now)
        {
            alarmTime.setTime(alarmTime.time + MILLISECONDS_PER_DAY);
        }
    
        // 如果響鈴計時器目前已經設定,則將其停止。
        alarmTimer.reset();
        // 計算在響鈴響起之前 (響鈴時間與目前時間的差異),
        // 必須經過多少毫秒,並將這個值設定為
        // 響鈴計時器的延遲時間。
        alarmTimer.delay = Math.max(1000, alarmTime.time - now.time);
        alarmTimer.start();
    
        return alarmTime;
    }

這個方法會執行數項工作,其中包含儲存響鈴訊息以及建立 Date 物件 (alarmTime) 代表響鈴要響起時的實際時間。與目前論述最有關聯的部分,也就是此方法的最後幾行,會設定並啟動 alarmTimer 變數的計時器。首先,呼叫它的 reset() 方法,如果計時器正在執行的話,這麼做便會將計時器停止並重新設定。接著,再從 alarmTime 變數的值中減去目前的時間 (以 now 變數表示),以判斷在響鈴響起之前還需多少毫秒。由於 Timer 類別不會在絕對時間觸發它的 timer 事件,所以這會是指定給 alarmTimerdelay 屬性的這個相對時間差。最後會呼叫 start() 方法,實際啟動計時器。

一旦經過指定的時間量之後,alarmTimer 便會傳送 timer 事件。由於 AlarmClock 類別已經將本身的 onAlarm() 方法註冊為該事件的偵聽程式,所以當 timer 事件發生時,就會呼叫 onAlarm()

    /**
     * 會在傳送 timer 事件時呼叫。
     */
    public function onAlarm(event:TimerEvent):void 
    {
        trace("Alarm!");
        var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage);
        this.dispatchEvent(alarm);
    }

註冊為事件偵聽程式的方法必須以適當的記號 (亦即此方法的參數集與傳回類型) 來定義。若要成為 Timer 類別之 timer 事件的偵聽程式,方法必須定義一個參數,而且此參數的資料類型必須是 TimerEvent (flash.events.TimerEvent),它是 Event 類別的子類別。當 Timer 實體呼叫本身的事件偵聽程式時,它會傳遞 TimerEvent 實體做為事件物件。

通知其它偵聽程式有關此響鈴事件

與 Timer 類別相似,AlarmClock 類別也可以在響鈴響起時,提供可允許其它程式碼接收通知的事件。對於要使用內建於 ActionScript 中之事件處理架構的類別而言,此類別必須實作 flash.events.IEventDispatcher 介面。最常見的作法是藉由擴充 flash.events.EventDispatcher 類別的方式來完成上述實作,這種方式能提供 IEventDispatcher 的標準實作 (或是藉由擴充 EventDispatcher 的其中一項子類別來完成)。如先前的內容所提及,AlarmClock 類別會擴充 SimpleClock 類別,接著依次擴充 Sprite 類別,然後 (經過一連串的繼承) 再擴充 EventDispatcher 類別。這些全部都表示 AlarmClock 類別已經有內建的功能來提供它自己的事件。

藉由呼叫 AlarmClock 從 EventDispatcher 繼承的 addEventListener() 方法,其它程式碼便可以註冊以接收 AlarmClock 類別之 alarm 事件通知。當 AlarmClock 實體已準備好通知其它程式碼該實體的 alarm 已經引發時,就會藉由呼叫 dispatchEvent() 方法來完成,這個方法也是繼承自 EventDispatcher。

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

下列程式碼是取自 AlarmClock 類別的 onAlarm() 方法 (已顯示在它之前的整個程式碼中)。呼叫 AlarmClock 實體的 dispatchEvent() 方法,這樣接著便會通知所有已觸發 AlarmClock 實體之 alarm 事件的已註冊偵聽程式。傳遞給 dispatchEvent() 的參數,就是將一併傳遞給偵聽程式方法的事件物件。在此範例中,它是 AlarmEvent 類別的實體,此類別是特別建立供這個範例使用的 Event 子類別。

提供自訂的 alarm 事件

所有事件偵聽程式都會接收事件物件參數 (包含遭觸發之特定事件的相關資訊)。在許多情況下,這個事件物件都會是 Event 類別的實體。然而,在某些情況下,提供事件偵聽程式額外的資訊會很有用。如本章先前所討論的內容,通常若要達到這個目的,您就必須定義新的類別 (Event 類別的子類別),並將此新類別的實體當做事件物件來使用。在此範例中,當傳送 AlarmClock 類別的 alarm 事件時,AlarmEvent 實體便會當做事件物件來使用。這裡所顯示的 AlarmEvent 類別會提供關於 alarm 事件的額外資訊,特別是響鈴訊息:

    import flash.events.Event;
    
    /**
     * 這個自訂的 Event 類別會將 message 屬性加入至基底 Event。
     */
    public class AlarmEvent extends Event 
    {
        /**
         * 新的 AlarmEvent 類型的名稱。
         */
        public static const ALARM:String = "alarm";
        
        /**
         * 可使用這個事件物件傳遞給事件處理常式。
         * 的文字訊息。
         */
        public var message:String;
        
        /**
         *  建構函式。
         *  @param message 響鈴響起時要顯示的文字。
         */
        public function AlarmEvent(message:String = "ALARM!")
        {
            super(ALARM);
            this.message = message;
        }
        ...
    }

要建立自訂事件物件類別的最佳方式,就是定義會擴充 Event 類別的類別,如先前的範例所示。為了補充所繼承的功能,AlarmEvent 類別會定義 message 屬性,此屬性包含了與該事件有關聯的響鈴訊息文字;message 值則會當做 AlarmEvent 建構函式中的參數來傳入。AlarmEvent 也會定義 ALARM 常數,此常數可以用來在呼叫 AlarmClock 類別的 addEventListener() 方法時,參考特定的事件 (alarm)。

除了加入自訂的功能外,每一個 Event 子類別都必須覆寫所繼承的 clone() 方法,做為 ActionScript 事件處理架構的一部分。Event 子類別也可以選擇性地覆寫所繼承的 toString() 方法,以便在呼叫 toString() 方法時,將自訂事件的屬性包含在傳回的值中。

    /**
     * 建立並傳回目前實體的副本。
     * @return 目前實體的副本。
     */
    public override function clone():Event
    {
        return new AlarmEvent(message);
    }
    
    /**
     * 傳回包含目前實體之所有屬性的
     * 字串。
     * @return 目前實體的字串形式。
     */
    public override function toString():String
    {
        return formatToString("AlarmEvent", "type", "bubbles", "cancelable", "eventPhase", "message");
    }

遭到覆寫的 clone() 方法必須傳回自訂 Event 子類別的新實體,並設定所有的自訂屬性以符合目前的實體。在遭到覆寫的 toString() 方法中,會使用公用程式方法 formatToString() (繼承自 Event) 以提供具有自訂類型名稱的字串,以及所有其屬性的名稱與值。


Flash CS3

 

有新的意見加入至這個頁面時,傳送電子郵件給我 | 意見報告

目前頁面: http://livedocs.adobe.com/flash/9.0_tw/main/00000140.html