Руководство по 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 ( ) вызваны не будут.

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

Public function containerClickListenerOne (e:MouseEvent):void { // Исключаем получение события функциями containerClickListenerTwo( ) // и chi1dClickListener( ) e. stopImmediatePropagation( );

}

С другой стороны, если функция containerClickListenerOne ( ) поглотит событие путем вызова метода stopPropagation ( ) вместо метода stoplmme diatePropagation ( ), то перед остановкой процесса диспетчеризации события будут вызваны оставшиеся приемники события MouseEvent. CLICK объекта container. Следовательно, функция containerClickListenerTwo ( ) получит событие, а функция childClickListener ( ) — нет.

public function containerClickListenerOne (e:MouseEvent):void { // Исключаем получение события только функцией childClickListener( ) e. stopPropagation( );

}

Обратите внимание, что предыдущий пример основывается на условии, что функция containerClickListenerOne ( ) была зарегистрирована перед функцией containerClickListenerTwo ( ). Дополнительную информацию о порядке, в котором вызываются приемники событий, можно найти в гл. 12.

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

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

Для реализации состояния «неактивен» в каждом объекте ToolPanel регистрируется метод clickListener ( ) для уведомления о возникновении события MouseEvent. CLICK в фазе захвата. Когда объект ToolPanel неактивен, метод clickListener ( ) останавливает все события щелчка кнопкой мыши до того, как они достигнут дочерних объектов Tool. В листинге 21.3 представлен класс ToolPanel, который был сильно упрощен, чтобы акцентировать внимание на коде, поглощающем событие (выделен полужирным шрифтом). В этом листинге дочерние элементы управления интерфейса класса ToolPanel являются экземплярами базового класса Tool, который отсутствует в листинге. Однако в реальном приложении эти элементы управления могут быть кнопками, меню или любыми другими видами интерактивных инструментов.

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

Листинг 21.3. Поглощение события

package { import flash. display. Sprite; import flash. events.*;

public class ToolPanel extends Sprite { private var enabled:Boolean;

public function ToolPanel ( ) { enabled = false;

var tool 1:Tool = new TooK ); var tool2:Tool = new TooK ); var tool3;Tool = new TooK );

tool 2.x = tool 1.width + 10;

tool 3.x = tool 2.x + tool 2.width + 10;

addChild(tooll); addChild(tool2); addChild(tool3);

// Регистрируем приемник в этом объекте для уведомлений // о возникновении события MouseEvent. CLICK в фазе захвата addEventListener(MouseEvent. CLICK, clickListener, true);

}

private function clickListener (e:MouseEvent):void { // Если данный объект ToolPanel неактивен… if (!enabled) {

// …останавливаем процесс диспетчеризации данного события -// щелчка кнопкой мыши, чтобы оно не достигло потомков данного // объекта ToolPanel

e. stopPropagation( );

traceC’Panel disabled. Click event dispatch halted.»);

}

}

}

}

В повседневной разработке приложений метод stopPropagation ( ) используется гораздо более часто, чем stopImmediatePropagation ( ). Тем не менее второй метод применяется в следующих ситуациях:

? когда объект-получатель желает, чтобы его собственные приемники не вызывались в результате возникновения события;

? когда программа не желает, чтобы приемники реагировали на данное событие.

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

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

? GameManager — класс, управляющий процессом игры;

? PlayerShip — класс, который представляет космический корабль игрока.

Класс GameManager определяет собственное событие GameManager. SHIP HIT, диспетчеризация которого осуществляется всякий раз, когда вражеская ракета попадает в корабль игрока. Получателем каждого события GameManager. SHIPHIT является объект PlayerShip. Этот объект регистрирует два приемника, которые реагируют на события GameManager. SHIP HIT. Один приемник проигрывает анимацию, имитирующую взрыв, а другой приемник воспроизводит звук взрыва.

Когда корабль игрока погибает, создается новый корабль, и на протяжении пяти секунд он остается неуязвимым. До тех пор пока корабль остается неуязвимым, приемники события GameManager. SHIP_HIT объекта PlayerShip не должны воспроизводить анимацию или звук «повреждения корабля».

Чтобы исключить выполнение приемников события GameManager. SHIP HIT до тех пор, пока корабль остается неуязвимым, класс PlayerShip регистрирует третий приемник hit Li stener ( ), предназначенный для поглощения событий GameManager. SHIPHIT на основании текущего статуса корабля (неуязвим или уязвим). Регистрация метода hitListener ( ) с приоритетом int, MAX_VALUE происходит в конструкторе класса PlayerShip, как показано в следующем коде:

public class PlayerShip { public function PlayerShip ( ) { addEventl_istener(GameManager. HIT, hitListener, false, int. MAX_VALUE);

}

}

В гл. 12 рассказывалось, что по умолчанию приемники событий объекта вызываются в том порядке, в котором они были зарегистрированы. Мы также знаем, что этот используемый по умолчанию «порядок вызова» может быть перекрыт с помощью параметра priority метода addEventListener ( ).

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

Поскольку при регистрации метода hitListener ( ) в конструкторе класса PlayerShip используется максимально возможный приоритет, из всех прием-

ников события GameManager. SHIP_HIT класса PlayerShip этот приемник всегда будет вызываться первым. Если объект PlayerShip является уязвимым и возникает событие GameManager. SHIP_HIT, метод hitListener ( ) не выполняет никаких действий. Но если объект PlayerShip не является уязвимым и возникает событие GameManager. SHIP_HIT, метод hitListener ( ) сначала поглощает это событие, а затем выполняет диспетчеризацию нового события PlayerShip. HIT DEFLECTED. После этого приемники, зарегистрированные для события PlayerShip. HIT_DEFLECTED, воспроизводят специальную анимацию и звук, которые сообщают о том, что корабль не был поврежден.

Далее представлен код метода hitListener ( ); обратите внимание на использование метода stopImmediatePropagation ( ):

private function hitListener (e:Event):void { if (invincible) { // Исключаем получение другими приемниками объекта PlayerShip // уведомления о возникновении события e. stopImmediatePropagation( ); // Рассылаем новое событие

dispatchEvent(new Event(PIayerShiр. HIT_DEFLECTED, true));

}

}

В предыдущем сценарии с классом PlayerShip стоит отметить, что, хотя объект PlayerShip может предотвратить вызов своих собственных приемников события GameManager. SHIP HIT, он не может предотвратить вызов приемников события GameManager. SHIP HIT, зарегистрированных в его отображаемых предках. В частности, любые приемники, зарегистрированные для фазы захвата в отображаемых предках объекта PlayerShip, будут всегда получать уведомление о возникновении события GameManager. SHIP_HIT, даже если объект PlayerShip поглотит это событие. Однако после того, как объект PlayerShip поглотит событие GameManager. SHIP_HIT, его предки не получат уведомление в фазе всплытия.

Теперь перейдем ко второму сценарию с использованием метода stopImmediatePropagation ( ), в котором программа желает, чтобы никакие приемники не отвечали на данное событие. Предположим, мы создаем набор компонент пользовательского интерфейса, которые автоматически переходят в неактивное состояние, когда среда выполнения теряет фокус операционной системы, и возвращаются в активное состояние, когда среда получает фокус операционной системы. Чтобы определить момент получения или потери фокуса операционной системы, наши компоненты регистрируют приемники для внутренних событий Event. ACTIVATE и Event. DEACTIVATE (дополнительные сведения об этих событиях можно найти в гл. 22).



Полезные ссылки
Случайные записи
  • 19.07.2010">Тестируем сайт правильно
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.16
  • 25.02.2011">Руководство по actionscript. часть 6, стр. 096
  • 27.02.2011">Руководство по actionscript. часть 6, стр. 024
  • 19.02.2013">Избавление от шлаков и токсинов
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 050
  • 22.07.2011">Ноутбук Acer Aspire 5583WXMi
  • 03.03.2011">Руководство по actionscript. часть 5, стр. 071
  • 08.03.2011">Руководство по actionscript. часть 4, стр. 078
  • 10.03.2011">Руководство по actionscript. часть 4, стр. 022
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 120
  • 02.03.2011">Руководство по actionscript. часть 5, стр. 098
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 070
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.87
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 006
Опрос

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

View Results

Loading ... Loading ...