イベント処理の例:Alarm Clock

Flash Player 9 以降、Adobe AIR 1.0 以降

Alarm Clock の例は、アラームが鳴り出す時刻をユーザーが指定できる時計と、その時刻に表示されるメッセージで構成されます。 Alarm Clock の例は、 日付と時刻の操作 の SimpleClock アプリケーションを基に作成されています。Alarm Clock は、次のような ActionScript 3.0 のイベントを操作するいくつかの機能を示しています。

  • イベントの監視と応答

  • リスナーへのイベントの通知

  • カスタムイベントタイプの作成

このサンプルの Flash Professional アプリケーションのファイルを入手するには、 http://www.adobe.com/go/learn_programmingAS3samples_flash_jp を参照してください。このサンプルの Flex アプリケーションのファイルを入手するには、 http://www.adobe.com/go/as3examples_jp を参照してください。Alarm Clock アプリケーションのファイルは、Samples/AlarmClock フォルダーにあります。 アプリケーションには次のファイルが含まれます。

ファイル

説明

AlarmClockApp.mxml

または

AlarmClockApp.fla

Flash(FLA)または Flex(MXML)のメインアプリケーションファイル。

com/example/programmingas3/clock/AlarmClock.as

SimpleClock クラスを拡張し、目覚まし時計の機能を追加するクラス

com/example/programmingas3/clock/AlarmEvent.as

AlarmClock クラスの alarm イベントのイベントオブジェクトとして機能するカスタムイベントクラス(flash.events.Event のサブクラス)

com/example/programmingas3/clock/AnalogClockFace.as

時計の丸い文字盤と時間に合わせた時針、分針、秒針を描画するコード(SimpleClock の例で説明)

com/example/programmingas3/clock/SimpleClock.as

単純な時刻合わせ機能を持つ時計インターフェイスコンポーネント(SimpleClock の例で説明)

Alarm Clock の概要

この例に示す時計の主な機能は、時刻を追跡して時計のディスプレイに表示すると共に、 日付と時刻の例:単純なアナログ時計 で説明しているとおり、SimpleClock アプリケーションコードを再利用することです。AlarmClock クラスは、アラーム時刻の設定やアラームが「鳴り出す」ときの通知の指定など、目覚まし時計に必要な機能を追加することで、前の例の SimpleClock クラスを拡張します。

イベントが作成された目的は、何かが発生したときの通知を行うためです。 AlarmClock クラスが Alarm イベントを公開し、他のオブジェクトは Alarm イベントを監視して、必要なアクションを実行できます。 また、AlarmClock クラスは Timer クラスのインスタンスを使用して、アラームをトリガーする時刻を判断します。 AlarmClock クラスと同様に、Timer クラスは指定された時間が経過すると、他のオブジェクト(この例では AlarmClock インスタンス)に通知するイベントを提供します。 ほとんどの ActionScript アプリケーションと同様に、イベントは Alarm Clock サンプルアプリケーションの機能の重要な部分を形成します。

アラームのトリガー

既に説明したように、AlarmClock クラスが実際に提供する機能は、アラームの設定とトリガーに関する機能だけです。 組み込みの Timer クラス(flash.utils.Timer)を使用して、指定された時間が経過した後で実行するようにコードを定義できます。 AlarmClock クラスは Timer インスタンスを使用して、アラームを鳴らす時刻を判断します。

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

AlarmClock クラスで定義された Timer インスタンスは alarmTimer と呼ばれます。AlarmClock インスタンスに必要なセットアップ操作を実行する initClock() メソッドは、 alarmTimer 変数を使用して 2 つの処理を行います。まず、Timer インスタンスが 0 ミリ秒待機し、タイマーイベントを 1 回だけトリガーするように指示するパラメーターを使用して、変数をインスタンス化します。 alarmTimer をインスタンス化した後、コードは変数の addEventListener() メソッドを呼び出し、変数の timer イベントを監視しようとしていることを示します。指定された時間が経過した後、 timer イベントを送出することで、Timer インスタンスが動作します。AlarmClock クラスは、独自のアラームを鳴らすために、いつ timer イベントが送出されたかを知る必要があります。 addEventListener() を呼び出すことで、AlarmClock コードは自分自身をリスナーとして alarmTimer に登録します。2 つのパラメーターは、AlarmClock クラスが timer イベントを監視しようとしていることを示し(定数 TimerEvent.TIMER で指定)、イベントが発生したときに、イベントに対する応答として AlarmClock クラスの onAlarm() メソッドを呼び出す必要があることを示しています。

実際にアラームを設定するために、AlarmClock クラスの setAlarm() メソッドが次のように呼び出されます。

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

このメソッドは、アラームメッセージの格納、Date オブジェクトの作成( alarmTime )、アラームが鳴る実際の時刻の表示など、複数の機能を実行します。この章と最も関係がある部分として、メソッドの最後の数行で、 alarmTimer 変数のタイマーが設定され、アクティブ化されます。まず、 reset() メソッドが呼び出され、タイマーが停止され、既に実行されていた場合はリセットされます。次に、現在時刻( now 変数で表現)が alarmTime 変数の値から減算され、アラームを鳴らすまでに経過する時間がミリ秒単位で決定されます。Timer クラスは timer イベントを絶対時間ではトリガーしないため、この相対的な時間差が alarmTimer delay プロパティに割り当てられます。最後に start() メソッドが呼び出され、タイマーが実際に開始されます。

指定された時間が経過すると、 alarmTimer timer イベントを送出します。AlarmClock クラスは、このイベントのリスナーとして onAlarm() メソッドを登録しているため、 timer イベントが発生すると、 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); 
    }

イベントリスナーとして登録されたメソッドは、適切なシグネチャ(つまり、メソッドのパラメーターと戻り値の型のセット)を使用して定義する必要があります。 メソッドを Timer クラスの timer イベントのリスナーとして使用するには、データ型が Event クラスのサブクラス TimerEvent(flash.events.TimerEvent)であるパラメーターを 1 つ定義する必要があります。Timer インスタンスはイベントリスナーを呼び出すときに、TimerEvent インスタンスをイベントオブジェクトとして渡します。

アラームのその他の事項の通知

Timer クラスと同様に、AlarmClock クラスはイベントを提供し、これによってアラームが鳴り出すときに他のコードが通知を受信できます。 ActionScript に組み込まれているイベント処理フレームワークをクラスで使用するには、そのクラスで flash.events.IEventDispatcher インターフェイスを実装する必要があります。 最も一般的な方法として、IEventDispatcher の標準実装を提供する flash.events.EventDispatcher クラスを拡張する方法があります(または、EventDispatcher のサブクラスのいずれかを拡張します)。先に説明したように、AlarmClock クラスによって SimpleClock クラスが拡張され、さらに SimpleClock クラスによって EventDispatcher クラスが拡張されています(継承のチェーンが利用されます)。すなわち、AlarmClock クラスには、既に独自のイベントを提供する組み込み機能があります。

他のコードは、AlarmClock が EventDispatcher から継承した addEventListener() メソッドを呼び出すことで、AlarmClock クラスの alarm イベントの通知を受けるように登録できます。 alarm イベントが生成されたことを AlarmClock インスタンスが他のコードに通知する準備ができている場合は、同様に EventDispatcher から継承された dispatchEvent() メソッドを呼び出して通知できます。

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

これらのコード行は、AlarmClock クラスの onAlarm() メソッドから取得されます(全体は前に示したとおりです)。AlarmClock インスタンスの dispatchEvent() メソッドが呼び出され、次に、AlarmClock インスタンスの alarm イベントがトリガーされたことが登録済みのすべてのリスナーに通知されます。 dispatchEvent() に渡されるパラメーターは、リスナーメソッドに渡されるイベントオブジェクトです。この例では、特に作成された Event サブクラスである AlarmEvent クラスのインスタンスです。

カスタムアラームイベントの提供

すべてのイベントリスナーが、トリガーされる特定のイベントに関する情報が設定されているイベントオブジェクトパラメーターを受け取ります。 多くの場合、イベントオブジェクトは Event クラスのインスタンスです。 ただし、場合によっては、追加の情報をイベントリスナーに提供すると便利なことがあります。 一般的にはこれを実現するために、新しいクラス(Event クラスのサブクラス)を定義し、このクラスのインスタンスをイベントオブジェクトとして使用します。この例では、AlarmClock クラスの alarm イベントが送出されたときに、AlarmEvent インスタンスがイベントオブジェクトとして使用されています。ここで示す AlarmEvent クラスは、 alarm イベントに関する追加の情報(具体的にはアラームメッセージ)を提供します。

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

カスタムイベントオブジェクトクラスを作成する最善の方法は、上述の例で示したように、Event クラスを拡張するクラスを定義することです。 継承された機能を補うために、AlarmEvent クラスでは、イベントに関連付けられたアラームメッセージのテキストを含むプロパティ message を定義しています。 message 値はパラメーターとして AlarmEvent コンストラクターに渡されます。AlarmEvent クラスは、定数 ALARM も定義します。これは、AlarmClock クラスの addEventListener() メソッドを呼び出すときに、特定のイベント( alarm )を参照するために使用できます。

カスタム機能を追加するほか、Event サブクラスでは、ActionScript イベント処理フレームワークの一部として継承された clone() メソッドをオーバーライドする必要があります。Event サブクラスでは、オプションで、 toString() メソッドが呼び出されたときに返される値にカスタムイベントのプロパティを含めるように、継承された 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"); 
    }

オーバーライドされた clone() メソッドは、現在のインスタンスに一致するすべてのカスタムプロパティセットを持つカスタム Event サブクラスの新しいインスタンスを返す必要があります。オーバーライドされた toString() メソッドは、ユーティリティメソッド formatToString() (Event から継承)を使用して、カスタムタイプの名前およびカスタムタイプのすべてのプロパティの名前と値が設定されたストリングを提供します。