Март 2011

Руководство по 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).

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

Предположим, мы разрабатываем тестовое приложение для выполнения нагрузочных испытаний наших компонентов. Наше приложение программным путем вызывает интерактивное поведение компонентов. В тесте мы должны гарантировать, что внутреннее событие Event. DEACTIVATE не переводит наши тестируемые компоненты в неактивное состояние. В противном случае наше тестовое приложение не сможет работать с ними программным путем. Таким образом, в конструкторе основного класса нашего текстового приложения мы регистрируем приемник для события Event. DEACTIVATE в экземпляре класса Stage. Этот приемник использует

метод stopImmediatePropagation ( ) для поглощения всех внутренних событий Event. DEACTIVATE, как показано в следующем коде:

private function deactivateListener (e: Event):void { e. stopImmediatePropagation( );

}

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

Приоритет и цепочка диспетчеризации событий

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

I Не существует способа сделать так, чтобы приемник одного объекта в цепочке дис-j « петчеризации события вызывался до или после приемника другого объекта в той же ¦^-Щ? цепочке.

Например, представьте объект Sprite, содержащий объект TextField. Объект Sprite регистрирует приемник spriteClickListener ( ) для события MouseEvent. CLICK — параметру useCapture установлено значение false, а параметру priority присвоено значение 2:

o6beKrSpr7′te. addEventLi stener (MouseEvent. CLICK, spriteClickListener, false. 2)

Точно так же объект TextField регистрирует приемник textClickListener ( ) для события MouseEvent. CLICK — значение параметра useCapture установлено в false, а параметру priority присвоено значение 1:

0бъектТехЬПе1с1. addEventLi stener (MouseEvent. CLICK, textClickListener, false. 1)

Когда пользователь щелкает кнопкой мыши на объекте TextField, среда Flash выполняет диспетчеризацию события MouseEvent. CLICK, получателем которого является объект TextField. В результате метод textClickListener ( ) вызывается в фазе получения перед методом spriteClickListener ( ), который вызывается в фазе всплытия. Два приемника события вызываются в порядке, устанавливаемом цепочкой диспетчеризации события, даже несмотря на то, что метод spriteClickListener ( ) был зарегистрирован с более высоким приоритетом, чем textClickListener ( ).

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

Дополнительную информацию о приоритетах событий можно найти в гл. 12.

Изменение иерархии отображения и цепочка диспетчеризации событий

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

Предположим, у нас есть экземпляр класса TextField, содержащийся в экземпляре класса Sprite, который, в свою очередь, содержится в экземпляре класса Stage. ПустьтaкжeмыpeгиcтpиpyeмпpиeмникstageClickListener ( ) вэкземпляре класса Stage для уведомления о возникновении события MouseEvent. CLICK в фазе захвата, как показано в следующем коде:

stage. addEventLi stener(MouseEvent. CLICK. stageCli ckLi stener, true):

Наконец, предположим, что зарегистрированная функция stageClickListener ( ) содержит код, который удаляет объект TextField из его родительского объекта Sprite, как показано в следующем коде:

private function stageClickListener (e:MouseEvent):void { // Если щелкнули кнопкой мыши на объекте TextField… if (е. target == textField) {

// …то удаляем его

removeChild(textField);

textField = null:

}

}

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

ФАЗА ЗАХВАТА: (1) Объект Stage

(2) Объект Sprite ФАЗА ПОЛУЧЕНИЯ: (3) Объект TextField ФАЗА ВСПЛЫТИЯ: (4) Объект Sprite

(5) Объект Stage

Когда начинается процесс диспетчеризации, среда Flash сначала уведомляет о возникновении события объект Stage (1). В результате этого уведомления вызывается приемник stageClickListener ( ) объекта Stage, который удаляет объект TextField из списка отображения. Далее, несмотря на то, что объект Sprite больше не является потомком объекта TextField, среда выполнения уведомляет о возникновении события объект Sprite (2). Затем, несмотря на то

что объекта Text Field больше нет в списке отображения, среда выполнения уведомляет о возникновении события объект TextField (3). Наконец, в фазе всплытия среда Flash снова уведомляет о возникновении события объекты Sprite (4) и Stage (5). Даже несмотря на то, что иерархия отображения получателя события была изменена в процессе диспетчеризации, событие все равно проходит по всей предопределенной цепочке диспетчеризации события.

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

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

В листинге 21.4 представлен код для приведенного сценария в контексте тестового класса DisappearingTextField. В этом листинге экземпляр пользовательского класса DisappearingTextField (подкласс класса Sprite) играет роль объекта Sprite из описанного сценария.

Листинг 21.4. Неизменяемая цепочка диспетчеризации события

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

public class DisappearingTextField extends Sprite { private var textField.-TextField; public function DisappearingTextField ( ) {

// Создаем объект TextField

textField = new TextField( );

textField. text = «Click here»;

textField. autoSize = TextFieldAutoSize. LEFT;

// Добавляем объект TextField в объект DisappearingTextField addChild(textField);

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

stage. addEventLi stener(MouseEvent. CLICK, staged ickListener, true);

// Чтобы доказать, что объект TextField получает уведомление

// о возникновении события MouseEvent. CLICK даже после того, как он

// будет удален из данного экземпляра класса DisappearingTextField,

// регистрируем приемник в объекте TextField для событий

// MouseEvent. CLICK

textFi eld. addEventLi stener(MouseEvent. CLICK, textFieldCli ckLi stener);

}

// Эта функция выполняется, когда пользователь щелкает кнопкой мыши

// на любом объекте в списке отображения

private function stageClickListener (e:MouseEvent):void {

// Если щелкнули кнопкой мыши на объекте TextField…



Полезные ссылки
Случайные записи
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 013
  • 19.03.2011">Руководство по actionscript. часть 2, стр. 090
  • 13.11.2012">Китай снял блокаду сервисов Google
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.121
  • 20.02.2012">Владельцы Twtter.com и Wikapedia.com оштрафованы за мошенничество
  • 04.09.2010">Красочность или функциональность?
  • 06.03.2011">Руководство по actionscript. часть 4, стр. 152
  • 18.08.2010">Как располагается информация о рабочем процессе
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.109
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.106
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 150
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.75
  • 16.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.17
  • 15.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.48
  • 27.08.2011">Размещение сервера в датацентре
Опрос

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

View Results

Loading ... Loading ...