Пример обработки событий: будильник

Flash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий

Пример будильника состоит из часов, которые дают пользователю возможность указать время отключения будильника, а также сообщение, которое необходимо показывать в это время. Пример будильника построен на приложении SimpleClock из раздела Работа с датами и временем. Будильник иллюстрирует несколько аспектов работы с событиями в ActionScript 3.0, включая:

  • прослушивание и реакцию на событие;

  • уведомляющие прослушиватели события;

  • создание заказного типа события.

Получить файлы приложения Flash Professional для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru. Получить файлы приложения Flex для этого примера можно на странице http://www.adobe.com/go/as3examples_ru. Файлы приложения «Будильник» находятся в папке Samples/AlarmClock. Приложение включает следующие файлы:

File

Описание

AlarmClockApp.mxml

или

AlarmClockApp.fla

Основной файл приложения Flash (FLA) или Flex (MXML).

com/example/programmingas3/clock/AlarmClock.as

Класс, который является расширением класса SimpleClock, добавляя к нему функцию будильника.

com/example/programmingas3/clock/AlarmEvent.as

Класс заказного события (подкласс flash.events.Event), который служит объектом события для события alarm класса AlarmClock.

com/example/programmingas3/clock/AnalogClockFace.as

Рисует на экране круглый циферблат, а также часовую, минутную и секундную стрелки на основе значения времени (см. описание в примере SimpleClock).

com/example/programmingas3/clock/SimpleClock.as

Компонент интерфейса часов с простыми функциональными возможностями хронометрирования (см. описание в примере SimpleClock).

Обзор программы «Будильник»

Основные функциональные возможности часов в данном примере, включая слежение за временем и отображение циферблата, повторно обращаются к коду приложения SimpleClock, который описан в разделе «Пример даты и времени: простые аналоговые часы». Класс AlarmClock является расширением класса SimpleClock из данного примера. Он добавляет в него функции, необходимые для будильника, включая установку времени сигнала и предоставление уведомления об «отключении» сигнала.

События созданы для того, чтобы предоставлять сведения о происходящем. Класс AlarmClock предоставляет событие Alarm, который другие объекты могут прослушивать, чтобы выполнить необходимые действия. Кроме того, класс AlarmClock использует экземпляр класса Timer, чтобы определить время включения сигнала. Как и класс AlarmClock, класс Timer предоставляет событие для уведомления других объектов (в данном случае экземпляра AlarmClock) по прошествии определенного промежутка времени. Как и в случае большинства приложений на языке ActionScript, события составляют важную часть функциональных возможностей образца приложения «Будильник».

Включение сигнала

Как было указано ранее, единственная функция, фактически обеспечиваемая классом 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); 
    }

Экземпляр Timer, определенный в классе AlarmClock, называется alarmTimer. Метод initClock(), который совершает необходимые операции установки для экземпляра AlarmClock, выполняет две операции с переменной alarmTimer. Во-первых, создается экземпляр переменной с параметрами, заставляющими экземпляр Timer выждать 0 миллисекунд и включить событие timer один раз. После создания экземпляра alarmTimer код вызывает метод addEventListener() этой переменной, чтобы указать, что он должен прослушивать событие timer. Экземпляр Timer действует путем отправки события timer по прошествии определенного периода времени. Классу AlarmClock потребуется информация о времени отправки события timer, чтобы включить собственный сигнал. Путем вызова метода addEventListener() код AlarmClock регистрируется как прослушиватель в alarmTimer. Два параметра указывают, что классу AlarmClock необходимо прослушивать событие timer (указанное константой TimerEvent.TIMER) и что когда это событие произойдет, метод onAlarm() класса AlarmClock необходимо вызвать в ответ на это событие.

Чтобы фактически установить сигнал, метод setAlarm() класса 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; 
    }

Этот метод выполняет ряд операций, включая сохранение сообщения сигнала и создание объекта Date (alarmTime), отражающего фактический момент выключения сигнала. Наибольшее отношение к обсуждаемой теме имеют последние несколько строк метода, где задан и активирован таймер переменной alarmTimer. Во-первых, вызывается его метод reset(), который останавливает таймер и сбрасывает его, если он уже запущен. Затем текущее значение времени (выражаемое переменной now) вычитается из значения переменной alarmTime, чтобы определить, сколько миллисекунд должно пройти перед тем, как будут отключен сигнал. Класс Timer не включает событие timer в абсолютное время, поэтому свойству delay переменной alarmTimer присваивается относительная временная разница. В итоге вызывается метод 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, метод должен определить один параметр с типом данных TimerEvent (flash.events.TimerEvent), относящийся к подклассу класса Event. Экземпляр Timer вызывает свои прослушиватели событий, передавая экземпляр TimerEvent в качестве объекта события.

Уведомление других пользователей о сигнале

Как и класс Timer, класс AlarmClock предоставляет событие, которое позволяет другому коду получать уведомления об отключении сигнала. Чтобы класс мог использовать систему обработки событий, встроенную в ActionScript, в этом классе должен быть реализован интерфейс flash.events.IEventDispatcher. Как правило, это выполняется путем расширения класса flash.events.EventDispatcher, являющегося стандартной реализацией IEventDispatcher (или путем расширения одного из подклассов EventDispatcher). Как было сказано выше, класс AlarmClock расширяет класс SimpleClock, который в свою очередь расширяет (через цепь наследования) класс EventDispatcher. Это означает, что класс AlarmClock уже имеет встроенные функциональные возможности для предоставления собственных событий.

Другой код может зарегистрироваться, чтобы получать уведомления о событии alarm класса AlarmClock путем вызова метода addEventListener(), который AlarmClock унаследовал от EventDispatcher. Когда экземпляр AlarmClock готов уведомить другой код о появлении события alarm, он делает это путем вызова метода dispatchEvent(), который также наследуется от EventDispatcher.

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

Эти строки кода взяты из метода onAlarm() класса AlarmClock (который ранее был показан целиком). Вызывается метод dispatchEvent() экземпляра AlarmClock, который в свою очередь уведомляет всех зарегистрированных прослушивателей о том, что инициировано событие alarm экземпляра AlarmClock. Параметр, переданный методу dispatchEvent(), является объектом события, который будет передан методам прослушивателя. В данном случае это экземпляр класса AlarmEvent: подкласса Event, созданного специального для этого примера.

Предоставление заказного события сигнала

Все прослушиватели событий получают параметр объекта события со сведениями об инициированном событии. Во многих случаях объект события является экземпляром класса Event. Однако в некоторых случаях полезно предоставить прослушивателям событий дополнительную информацию. Распространенным способом для этого является определение нового класса (подкласса класса Event) и использование экземпляра этого класса в качестве объекта события. В данном примере экземпляр AlarmEvent использован в качестве объекта события при отправке события alarm класса AlarmClock. Показанный здесь класс 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, которую можно применять для того, чтобы сослаться на конкретное событие (alarm) при вызове метода addEventListener() класса AlarmClock.

Помимо добавления заказных функций каждый подкласс Event должен переопределить унаследованный метод clone() как часть инфраструктуры обработки событий в ActionScript. Подклассы событий могут также при желании переопределять унаследованный метод 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) используется для предоставления строки с именем заказного типа, а также имен и значений всех его свойств.