Руководство по actionscript. часть 4, стр. 013

НекийОтображаемыйОбъект. stage. remveEventlistener (MouseEvent. CLICK,

clickListener, true);

некийОтображаемыйОбъект. stage. removeEventLi stener(MouseEvent. CLICK,

clickListener. false);

*v А щ отдельной операцией, отмена каждой регистрации должна осуществляться соответ-

Поскольку каждая регистрация приемника с помощью метода addEventtistener() считается отдельной операцией, отмена каждой регистращ Щ ствующим вызовом метода removeEventListener().

Теперь, когда мы получили общее представление о цепочке диспетчеризации события, рассмотрим пример, который демонстрирует, как цепочка диспетчеризации события может помочь централизовать код в реальном приложении.

Использование цепочки диспетчеризации событий для централизации кода

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

Руководство по actionscript. часть 4, стр. 014

Предположим, что мы создаем простой элемент управления «флажок», состоящий из двух следующих классов:

? CheckBox — подкласс класса Sprite, который выступает в роли контейнера для всего элемента управления;

? CheckBoxI con — подкласс класса Sprite, который представляет графический значок флажка.

На этапе выполнения каждый экземпляр класса CheckBox создает два дочерних объекта: экземпляр класса CheckBoxI con для значка флажка и экземпляр класса TextField для текстовой надписи флажка. Для справочных целей назовем экземпляр основного класса CheckBox именем container, а два его дочерних объекта — icon и label. На рис. 21.3 представлена схема нашего элемента управления «флажок».

container _* „ Щелкните \

(экземпляр \J? J_ здесь ;

класса CheckBox) /~~~~’

, icon label (экземпляр (экземпляр класса CheckBoxIcon) TextF?,d)

Рис. 21.3. Объекты элемента управления «флажок»

Мы хотим максимально упростить использование нашего флажка, поэтому проектируем его таким образом, чтобы состояние флажка — установлен или снят — изменялось в тот момент, когда пользователь щелкает кнопкой мыши на значке флажка или на его надписи. Соответственно, в нашей реализации мы должны отслеживать события щелчка кнопкой мыши, получателями которых являются объекты icon и label.

Руководство по actionscript. часть 4, стр. 015

Мы могли бы зарегистрировать отдельные приемники для события щелчка кнопкой мыши в каждом из указанных объектов. Однако регистрация двух приемников событий приведет к увеличению длительности разработки и из-за повторения практически идентичного кода для регистрации приемников увеличит вероятность появления ошибок в нашем флажке. Вместо этого, чтобы избежать появления повторяющегося кода, мы можем обрабатывать все события щелчка кнопкой мыши в одном приемнике, зарегистрированном в объекте container. Поскольку объект container является отображаемым предком и для объекта icon, и для объекта label, он получает уведомления всякий раз, когда среда Flash выполняет диспетчеризацию события щелчка кнопкой мыши, получателем которого является любой из этих объектов. Когда выполняется код приемника объекта container, обрабатывающий события щелчка кнопкой мыши, мы знаем, что пользователь щелкнул либо на значке, либо на надписи, и в ответ на это действие мы можем изменить состояние флажка — установить или снять.

В листинге 21.2 представлен код для нашего примера с флажком. Части кода, связанные с обработкой событий, выделены полужирным шрифтом.

Листинг 21.2. Иерархическая обработка событий класса CheckBox

// Файл CheckBox. as package {

import flash. display.*;

import flash. events.*;

import flash. text.*;

// Очень простой элемент управления «флажок»

public class CheckBox extends Sprite { private var label-.TextField; // Текстовая надпись флажка private var icon:CheckBoxIcon; // Графический значок флажка private var checked:Boolean; // Флаг, который указывает, установлен

// ли флажок в настоящий момент

// Конструктор

public function CheckBox (msg:String) { // При создании объекта флажок не установлен checked = false;

// Создаем графический значок icon = new CheckBoxIcon( );

// Создаем текстовую надпись label = new TextField( ); label. text = msg;

label. autoSize = TextFieldAutoSize. LEFT; label. selectable = false;

// Размещаем текстовую надпись рядом с графическим значком label. х = icon. x + icon. width + 5;

// Добавляем объекты label и icon к данному объекту в качестве // его отображаемых детей addChild(icon); addChild(label);

// Регистрируем приемник для получения событий щелчка кнопкой мыши, // получателем которых является данный объект или любой // из его дочерних объектов (то есть label или icon) addEventListener(MouseEvent. CLICK, clickListener);

‘}

// Обрабатывает события щелчка кнопкой мыши. Этот метод выполняется // всякий раз, когда пользователь щелкает на объекте label или icon, private function clickListener (e:MouseEvent):void { if (checked) { icon. uncheck( ); checked = false; } else { icon. check( ); checked = true;

}

}

}

// Файл CheckBoxIcon. as package { import flash. display.*;

// Графический значок для элемента управления «флажок» public class CheckBoxIcon extends Sprite {

// Конструктор

public function CheckBoxIcon ( ) { uncheck( );

}

// Рисует значок флажка в состоянии «установлен» public function check ( ):void {

graphics. clear( );

graphics. lineStyle(l);

graphics. beginFi11(OxFFFFFF);

graphics. drawRect(0, 0, 15. 15);

graphics. endFill( );

graphics. lineTo(15, 15);

graphics. moveTo(0, 15); graphics. lineTo(15. 0);

}

// Рисует значок флажка в состоянии «снят» public function uncheck ( ):void {

graphics. clear( );

graphics. lineStyle(l);

graphics. beginFill(OxFFFFFF);

graphics. drawRect(0. 0, 15, 15);

}

}

}

// Файл CheckBoxDemo. as (основной класс, который использует класс CheckBox) package { import flash. display. Sprite;

// Демонстрирует использование класса CheckBox public class CheckboxDemo extends Sprite { public function CheckboxDemo( ) { var с;CheckBox = new CheckBox(«Click here»); addChild(c);

}

}

}

Мы познакомились с основами системы иерархической диспетчеризации событий языка ActionScript, но нам осталось рассмотреть еще несколько тем. Не будем сдаваться.

Руководство по actionscript. часть 4, стр. 016

Определение текущей фазы события

Как уже известно из подразд. «Регистрация приемника предка для фазы захвата и фазы всплытия» разд. «Приемники событий и цепочка диспетчеризации событий», дважды вызвав метод addEventListener ( ), можно зарегистрировать одну и ту же функцию-приемник события как для фазы захвата, так и для фазы всплытия процесса диспетчеризации события. В подразд. «Двойное назначение параметра useCapture» разд. «Приемники событий и цепочка диспетчеризации событий» мы также узнали, что приемник события, при регистрации которого параметру useCapture было установлено значение false, может вызываться как в фазе получения, так и в фазе всплытия диспетчеризации события. Следовательно, когда в ответ на возникшее событие выполняется функция-приемник события, текущая фаза события будет известна не всегда. В соответствии с этим язык ActionScript предоставляет переменную экземпляра eventPhase класса Event, которая может быть использована внутри функции-приемника события для определения текущей фазы события.

Переменная eventPhase содержит информацию о том, в какой фазе находится текущий процесс диспетчеризации события — захвата, получения или всплытия.

Когда процесс диспетчеризации события находится в фазе захвата, переменной eventPhase присваивается значение EventPhase. CAPTURING_PHASE, которое означает, что объект-получатель еще не получил уведомление о возникновении события.

Когда процесс диспетчеризации события находится в фазе получения, переменной eventPhase присваивается значение EventPhase. ATTARGET, которое означает, что в настоящий момент объект-получатель обрабатывает событие.

Когда процесс диспетчеризации события находится в фазе всплытия, переменной eventPhase присваивается значение EventPhase. BUBBLING_PHASE, которое означает, что объект-получатель завершил обработку события.

Обычно константам EventPhase. CAPTURING_PHASE, EventPhase. AT_TARGET и EventPhase. BUBBLING_PHASE присваиваются значения 1, 2 и 3 соответственно, но эти значения со временем могут измениться, поэтому использовать их непосредственно в коде не следует. Вместо этого, чтобы определить текущую фазу события внутри функции-приемника события, всегда сравнивайте значение переменной eventPhase с константами класса EventPhase. Например, всегда используйте код наподобие следующего:

private function someListener (e:Event):void { if (e. eventPhase = EventPhase. AT TARGET) {

// Этот приемник был вызван в фазе получения…

Руководство по actionscript. часть 4, стр. 017

}

}

И никогда не используйте код наподобие следующего:

private function someListener (e:Event):void { // Плохой код! Никогда не используйте в коде // непосредственные значения // констант класса EventPhase!

if (е. eventPhase == 2) { // Этот приемник был вызван в фазе получения…

}

}

Следующий код демонстрирует общий подход к использованию переменной eventPhase. Сначала в экземпляр класса Stage добавляется объект TextField. Затем в экземпляре класса Stage регистрируется приемник clickListener ( ) для получения уведомлений о возникновении события MouseEvent. CLICK в фазе захвата.

Наконец, в экземпляре класса Stage регистрируется приемник clickListener ( ) для получения уведомлений о возникновении события MouseEvent. CLICK в фазе получения и в фазе всплытия.

Руководство по actionscript. часть 4, стр. 018

При выполнении приемника clickListener ( ) на консоль выводится текущая фаза. Обратите внимание, что она определяется путем сравнения значения переменной eventPhase с тремя константами класса EventPhase.

var t:TextField = new TextField( ); t. text = «click here»;

t. autoSize = TextFieldAutoSize. LEFT; stage. addChild(t):

// Регистрируем приемник для фазы захвата

stage. addEventListener(MouseEvent. CLICK, clickListener, true);

// Регистрируем приемник для фазы получения или всплытия stage. addEventListener(MouseEvent. CLICK, clickListener, false);

// …где-то в классе

private function clickListener (e;MouseEvent);void { var phase:String; switch (e. eventPhase) {

case EventPhase. CAPTURING_PHASE:

phase = «Capture»;

break;

case EventPhase. AT_TARGET; phase = «Target»; break;

case EventPhase. BUBBLING_PHASE;

phase = «Bubbling»;

break;

}

trace(«Current event phase; » + phase);

}

Если при выполнении предыдущего кода пользователь щелкнет кнопкой мыши на объекте TextField, то среда Flash осуществит диспетчеризацию события MouseEvent. CLICK, получателем которого является объект TextField, и в результате будет выведена следующая информация:

Current event phase: Capture Current event phase: Bubbling

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

Руководство по actionscript. часть 4, стр. 019

С другой стороны, если пользователь щелкнет кнопкой мыши в области отображения, среда Flash выполнит диспетчеризацию события MouseEvent. CLICK, получателем которого является объект Stage, и в результате будет выведена следующая информация:

Current event phase: Target

Как будет рассмотрено в следующем разделе, переменная eventPhase обычно используется для отличия событий, получателем которых является некий объект, от событий, получателями которых являются потомки этого объекта. Реже переменная eventPhase применяется для отличия фазы захвата от фазы всплытия внутри приемников предка, зарегистрированных для обеих фаз.

Отличие событий, получателем которых является некий объект, от событий, получателями которых являются его потомки

Когда переменной eventPhase объекта Event, передаваемого в функцию-приемник, присвоено значение EventPhase. AT TARGET, мы знаем, что получателем события является объект, в котором зарегистрирован данный приемник. С другой стороны, когда переменной eventPhase присвоено значение EventPhase. CAPTURING_PHASE или EventPhase. BUBBLING_PHASE, мы знаем, что получателем события является потомок объекта, в котором зарегистрирован данный приемник.

Таким образом, приемник может использовать следующий код, чтобы игнорировать события, получателями которых являются потомки объекта, зарегистрировавшего этот приемник:

private function некийПриемник (е:НекоеСобытие):void { if (е. eventPhase == EventPhase. ATJARGET) { // Этот код выполняется только в том случае, если получателем события // является объект, зарегистрировавший данный приемник.

}

}

Мы можем использовать предыдущую методику, чтобы написать код, который реагирует на события ввода, получаемые неким конкретным объектом, но не его потомками. Например, представьте приложение, в котором экземпляр класса Stage содержит множество кнопок, текстовых полей и других объектов для ввода данных. Чтобы реагировать только на щелчки кнопкой мыши, которые происходят над незаполненными областями экземпляра класса Stage, мы используем следующий код:

// Регистрируем приемник в экземпляре класса Stage для событий // MouseEvent. CLICK. В результате метод clickListener( ) будет вызываться // всегда, когда щелкают на *любом* объекте в списке отображения, stage. addEventLi stener(MouseEvent. CLICK, cli ckLi stener);

// …где-то в классе определяем приемник события MouseEvent. CLICK

private function clickListener (e:MouseEvent):void {

// Если этот приемник был вызван в фазе получения…

Руководство по actionscript. часть 4, стр. 020

If (е. eventPhase == EventPhase. ATJARGET) { // …значит щелкнули на экземпляре класса Stage. Продолжаем выполнение // кода для ситуации «Щелкнули на экземпляре класса Stage».

}

}

Чтобы создать приемник, игнорирующий события, получателем которых является зарегистрировавший его объект, мы используем следующий код:

private function некийПриемник (е:некоеСобытие):чо1б { if (е. eventPhase!= EventPhase. AT_TARGET) { // Этот код выполняется только в том случае, если получателем события // является потомок объекта, в котором был зарегистрирован данный // приемник.

}

}

Например, следующий приемник реагирует на щелчки кнопкой мыши, которые происходят над любым объектом в списке отображения, но не над пустой областью экземпляра класса Stage:

// Регистрируем приемник в экземпляре класса Stage для событий // MouseEvent. CLICK

stage. addEventLi stener(MouseEvent. CLICK, cli ckLi stener);

// …где-то в классе определяем приемник события MouseEvent. CLICK

private function clickListener (e:SomeInputEvent):void { // Если этот приемник не был вызван на фазе получения… if (е. eventPhase!= EventPhase. AT_TARGET) {

// …получателем события является потомок экземпляра класса Stage.

Руководство по actionscript. часть 4, стр. 021

// Следовательно, в момент щелчка указатель мыши находился над одним

// из объектов в списке отображения, но не над пустой областью

// экземпляра класса Stage.

}

}

Перейдем к следующей теме, относящейся к процессу иерархической диспетчеризации событий, — рассмотрим остановку процесса диспетчеризации события.

Остановка процесса диспетчеризации события

В любой точке цепочки диспетчеризации события каждый приемник события — включая приемники, зарегистрированные в объекте-получателе, и приемники, зарегистрированные в предках объекта-получателя, — может остановить весь процесс диспетчеризации. Остановка процесса диспетчеризации события называется поглощением события.

Чтобы остановить процесс диспетчеризации события, мы вызываем метод экземпляра stopImmediatePropagat ion ( ) или stopPropagation ( ) класса Event над объектом Event, передаваемым в функцию-приемник. Метод stoplmmediat ePropagation ( ) останавливает процесс диспетчеризации события немедленно, не позволяя вызвать оставшиеся приемники; метод stopPropagation ( ) останавливает процесс диспетчеризации события после того, как среда Flash вызовет оставшиеся приемники, зарегистрированные в объекте, который на настоящий момент получил уведомление о возникновении события.

Руководство по actionscript. часть 4, стр. 022

Предположим, что у нас есть экземпляр класса Sprite — container, который содержит объект TextField — child:

var container:Sprite = new Sprite( ); var chiId:TextField = new TextField( ): child. text = «click here»: chiId. autoSize = TextFieldAutoSize. LEFT; contai ner. addChiIdCchiId):

Предположим также, что у нас есть три функции-приемника: containerClickLis tenerOne ( ), containerClickListenerTwo ( ) и childClickListener ( ). Регистрируем функции containerClickListenerOne ( ) и containerClic kListenerTwo ( ) в объекте container для получения уведомлений о возникновении события MouseEvent. CLICK в фазе захвата:

container. addEventListener(MouseEvent. CLICK,

contai nerCli ckLi stenerOne. true);

contai ner. addEventLi stener(MouseEvent. CLICK,

contai nerCli ckLi stenerTwo, true):

После этого регистрируем функцию childClickListener ( ) в объекте chi Id для уведомлений о возникновении события MouseEvent. CLICK в фазе получения:

child. addEventLi stener(MouseEvent. CLICK, chi1dCli ckLi stener, false);

В обычной ситуации, когда пользователь щелкает кнопкой мыши на объекте child, вызываются все три приемника события: два в фазе захвата и один в фазе получения. Если тем не менее функция containerClickListenerOne ( ) поглотит событие путем вызова метода stopImmediatePropagation ( ), ни containerClickLi stenerTwo ( ), ни childClickListener ( ) вызваны не будут.



Полезные ссылки
Случайные записи
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 094
  • 11.08.2010">Популярное расположение контактной информации
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 074
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 015
  • 22.01.2011">Руководство по actionscript. часть 1, стр. 140
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 052
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 138
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 069
  • 13.03.2011">Руководство по actionscript. часть 3, стр. 113
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 070
  • 08.09.2011">Есть ли предел у интернета?
  • 27.02.2011">Руководство по actionscript. часть 6, стр. 044
  • 19.02.2014">О пользе массажа
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.17
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.27
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...