Архив рубрики «часть 4»

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

ГЛАВА 21

События и иерархии отображения

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

Система диспетчеризации событий через иерархию объектов языка ActionScript, о кото-л ч рой пойдет речь в этой главе, основана на спецификации Document Object Model (DOM) За’ Level 3 Events Specification консорциума W3C, доступной по адресу http://www. w3.org/

TR/DOM-Level-3-Events.

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

Как мы уже видели в гл. 12, когда среда Flash выполняет диспетчеризацию события, получателем которого является объект, не входящий в состав иерархии отображения, этот получатель будет единственным, кто узнает о возникновении события. Например, когда завершается воспроизведение звукового файла в объекте Sound, среда Flash выполняет диспетчеризацию события Event. COMPLETE, получателем которого выступает соответствующий объект SoundChannel. Этот объект не входит в состав иерархии отображения, поэтому он будет единственным объектом, который узнает о возникновении этого события.

В отличие от этого, когда среда Flash выполняет диспетчеризацию события, получателем которого является объект, входящий в состав иерархии отображения, этот получатель и все его предки в иерархии отображения узнают о возникновении события. Например, если объект Sprite содержит объект TextField и пользователь щелкает кнопкой мыши на втором объекте, то и TextField (получатель события), и Sprite (предок получателя события) узнают о том, что произошел щелчок кнопкой мыши.

Система иерархической диспетчеризации событий языка ActionScript позволяет каждому контейнеру отображаемых объектов регистрировать приемники для обработки событий, получателями которых являются отображаемые объекты-потомки этого контейнера. Например, объект Sprite, представляющий окно, может зарегистрировать приемник, обрабатывающий события о щелчке кнопкой мыши, получателем которых является вложенный элемент управления «кнопка ОК». Или объект Sprite, представляющий форму для авторизации, может зарегистрировать приемник, обрабатывающий события фокуса, получателями которых являются вложенные поля ввода.

Продолжение:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,

41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,

77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,

109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,

135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155

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

Такая централизованная архитектура позволяет сократить объемы повторяющегося кода, особенно реагирующего на события пользовательского ввода. Далее, в разд. «Использование цепочки диспетчеризации события для централизации кода», мы рассмотрим пример, который демонстрирует преимущества централизованной обработки событий. Но для начала познакомимся с основами иерархической диспетчеризации событий и регистрации.

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

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

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

Для некоторых типов событий процесс диспетчеризации завершается сразу после окончания фазы получения. Для остальных типов событий процесс диспетчеризации переходит в третью фазу, называемую фазой всплытия. На этой фазе предки объекта-получателя узнают о том, что получатель был успешно уведомлен о возникновении события. События, имеющие фазу всплытия, называются всплывающими] события, не имеющие фазу всплытия, называются невсплывающими.

У четырех типов событий — Event. ACTIVATE, Event. DEACTIVATE, Event. ENTER_FRAME и Event. RENDER — есть только фаза получения. Процесс диспетчеризации всех остальных событий, получателем которых является объект в иерархии отображения, включает фазу захвата и фазу получения. Некоторые типы событий также имеют фазу всплытия.

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

которого уведомление о событии передается вниз через предков объекта-получателя (фаза захвата) к объекту-получателю (фаза получения) и обратно через его предков (фаза всплытия), называется цепочкой диспетчеризации события. Когда уведомление о событии проходит по цепочке диспетчеризации события, говорят, что событие передается от объекта к объекту.

Рассмотрим простой пример цепочки диспетчеризации события. Предположим, что экземпляр класса Stage содержит объект Sprite, который, в свою очередь, содержит объект TextField, как показано на рис. 21.1. Видно, что корнем иерархии отображения объекта TextField является экземпляр класса Stage, а непосредственным родителем объекта TextField — объект Sprite.

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

Теперь предположим, что пользователь вводит некий текст в объект TextField, в результате чего среда Flash вынуждена выполнить диспетчеризацию события TextEvent. TEXT INPUT, получателем которого является объект TextField. Поскольку объект TextField является частью иерархии отображения, событие передается по цепочке диспетчеризации события. В первой фазе процесса (фазе захвата) уведомление о возникновении события сначала получает экземпляр класса Stage, а затем — экземпляр класса Sprite. Во второй фазе (фазе получения) уведомление о возникновении события получает сам объект TextField. Наконец, в третьей фазе процесса (фазе всплытия) уведомление о том, что получатель был уведомлен о возникновении события, сначала получает экземпляр класса Sprite, а затем — экземпляр класса Stage. Всего в процессе диспетчеризации события TextEvent. TEXT INPUT происходит пять уведомлений о возникновении события, как показано на рис. 21.2.

Экземпляр I класса Stagel

Рис. 21.1. Пример иерархии отображения

Фаза захвата

Уведомлен экземпляр класса Stage

Экземпляр класса Stagel

Уведомлен объект Sprite

Уведомлен экземпляр класса Stage

t

Объект Sprite

Уведомлен объект Sprite

А

Объект TextField

Уведомлен объект TextField

Фаза всплытия

Фаза получения

Рис. 21.2. Цепочка диспетчеризации для события TextEvent. TEXT_INPUT

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

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

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

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

Чтобы зарегистрировать приемник в предке получателя события для фазы захвата диспетчеризации события, мы устанавливаем третьему параметру useCapture метода addEventListener ( ) значение true, как показано в следующем коде:

предок. addEventListener(событие, приемник, true)

Эта строка кода заставляет метод приемник( ) выполняться всякий раз, когда среда Flash осуществляет диспетчеризацию события событие, получателем которого является один из потомков объекта предок, до того как потомки получат уведомление о возникновении этого события.

Чтобы зарегистрировать приемник в предке получателя события для фазы всплытия диспетчеризации события, мы устанавливаем третьему параметру useCapture метода addEventListener ( ) значение false, как показано в следующем коде:

предок. addEventLi stener(событие, приемник, false)

В качестве альтернативы, поскольку в качестве значения по умолчанию параметра useCapture используется false, мы можем просто опустить аргумент useCapture, как показано в следующем коде:

предок. addEventLi stener(событие, приемник)

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

*«,

^ I Для краткости в оставшейся части этой главы мы будем использовать неофициальный м$ J* термин «приемник предка», который обозначает «приемник события, зарегистриро-—__За* ванный в отображаемом предке получателя события». Подобным образом, мы будем использовать термин «приемник получателя», который обозначает «приемник события, зарегистрированный непосредственно в получателе события».

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

При регистрации приемника предка для невсплывающего события мы всегда выполняем регистрацию для фазы захвата (то есть в качестве значения параметра useCapture передаем true). В противном случае этот приемник вызван не будет. При регистрации приемника предка для всплывающего события мы выбираем уведомления либо в фазе захвата (значение параметра useCapture — true), либо в фазе всплытия (значение параметра useCapture — false), или же оба типа уведомлений, в зависимости от потребностей приложения.

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

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

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

В отличие от приемников предков, приемники, зарегистрированные в получателе события, могут вызываться только в одной фазе — фазе получения. Чтобы зарегистрировать приемник в получателе события для фазы получения процесса диспетчеризации события, мы регистрируем этот приемник с помощью вызова метода addEventListener ( ), третьему параметру useCapture которого устанавливается значение false, — точно так же, как мы регистрируем приемник предка для получения уведомлений на фазе всплытия. Этот подход демонстрирует следующий обобщенный код:

получательСобытия. addEventListener{событие, приемник, false) Или просто:

получательСобытия. addEventListener{событие, приемник)

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

* *.

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

^ I При регистрации приемника события непосредственно в получателе события для уведом-

*S: л щ лений на фазе получения параметр useCapture должен быть всегда установлен в значение

*yj false или вообще опущен. В противном случае приемник никогда не будет вызван.

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

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

Как мы уже знаем, чтобы зарегистрировать приемник предка для уведомлений о возникновении события в фазе захвата, мы устанавливаем параметру useCapture метода addEventListener ( ) значение true, как показано в следующем коде:

предок. addEventListener{событие, приемник, true)

Теперь используем этот код в работающем примере. Для тестовой иерархии отображения возьмем сценарий, который был изображен на рис. 21.1,— экземпляр класса Stage включает в себя объект Sprite, который, в свою очередь, содержит объект TextField. В листинге 21.1 представлен код для создания этой иерархии.

Листинг 21.1. Тестовая иерархия отображения

// Создаем экземпляр класса Sprite var theSprite:Sprite = new Sprite( );

// Создаем экземпляр класса TextField var theTextFi eld.-TextField = new TextField( ); theTextField. text = «enter input here»; theTextField. autoSize = TextFieldAutoSize. LEFT; theTextField. type = TextFieldType. INPUT;

// Добавляем объект TextField в объект Sprite theSprite. addChi1d(theTextFi eld);

// Добавляем объект Sprite в экземпляр класса Stage. Обратите внимание. // что объект некийОтображаемыйОбъект должен находиться в списке // отображения, чтобы иметь доступ к экземпляру класса Stage. некийОтображаемыйОбъект. stage. addChi1d(theSpri te);

Предположим, что мы хотим зарегистрировать функцию textlnputListener ( ) в объекте theSprite для событий TextEvent. TEXT_INPUT. Вот код функции textlnputListener ( ):

private function textlnputListener (e:TextEvent):void { traceCThe user entered some text»):

}

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

theSprite. addEventListener(TextEvent. TEXT_INPUT. textlnputListener. true)

Предыдущая строка кода заставляет функцию textlnputListener ( ) выполняться всякий раз, когда среда Flash осуществляет диспетчеризацию события TextEvent. TEXT_INPUT, получателем которого является объект theTextField, до того как объект theTextField получит уведомление о возникновении этого события.

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

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

Напомним, что для регистрации приемника предка для уведомлений о возникновения события в фазе всплытия мы устанавливаем параметру useCapture метода addEventListener ( ) значение false, как показано в следующем коде:

предок. addEventLi stener{событие, приемник, false)

Продолжая работу с нашим объектом TextField из листинга 21.1, предположим, что мы хотим зарегистрировать функцию textlnputListener ( ) в объекте

theSprite для событий TextEvent. TEXT_INPUT. При этом мы хотим, чтобы функция textlnputListener ( ) вызывалась в фазе всплытия (то есть после получения уведомления о возникновении события объектом TextField). Мы используем следующий код:

theSpri te. addEventLi stener(TextEvent. TEXT_INPUT. textInputLi stener. false)

Можно сделать то же самое, полностью опустив значение параметра useCapture:

theSprite. addEventListener(TextEvent. TEXT_INPUT. textlnputListener)

Эта строка кода заставляет функцию textlnputListener ( ) выполняться всегда, когда среда Flash осуществляет диспетчеризацию события TextEvent. TEXT_INPUT, получателем которого является объект theTextField, но после того, как объект theTextField получит уведомление о возникновении этого события.

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

Обратите внимание, что, если бы событие TextEvent. TEXT_INPUT было не-всплывающим, функция textlnputListener ( ) никогда бы не была вызвана. Стоит еще раз повторить то, о чем мы узнали ранее: если приемник предка регистрируется для невсплывающего события либо с опущенным параметром useCapture, либо с параметром useCapture, которому установлено значение true, этот приемник никогда не будет вызван. Чтобы приемник предка вызывался при диспетчеризации невсплывающего события, он должен быть зарегистрирован для фазы захвата с параметром useCapture, которому установлено значение true.

Чтобы определить, каким является событие, можно воспользоваться любым из следующих способов.

? Обратиться к описанию события в справочнике по языку ActionScript корпорации Adobe.

? Обработать событие с помощью приемника события либо в фазе захвата, либо на фазе получения, и проверить значение переменной bubbles объекта Event, переданного в этот приемник. Если значение переменной bubbles равно true, событие является всплывающим; в противном случае — невсплы-вающим.

Следующий код демонстрирует последнюю методику:

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

некийОтображаемыйОбъект. stage. addEventListener(MouseEvent. CLICK. clickListener);

// …далее в коде определяем функцию elickListener( ) private function clickListener (e:MouseEvent):void {

// Когда возникает событие, проверяем, является ли оно всплывающим

if (е. bubbles) { traceC’The MouseEvent. CLICK event is a bubbling event.»):

} else {

trace(«The MouseEvent. CLICK event is a non-bubbling event.»);

Для удобства поиска во всех разделах справочника по языку ActionScript корпорации Adobe, где описываются внутренние события, указано значение переменной экземпляра bubbles класса Event. Как правило, большинство внутренних событий, получателями которых являются отображаемые объекты, — всплывающие.

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

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

Чтобы указать, что приемник предка должен вызываться и в фазе захвата, и в фазе всплытия (то есть до и после того, как получатель будет уведомлен о возникновении события), мы должны зарегистрировать этот приемник дважды — один раз параметр useCapture должно быть установлено значение true, а другой раз — значение false. Например, возвращаясь к нашему сценарию с объектом TextField, предположим, что мы хотим зарегистрировать наш приемник textlnputListener ( ) в объекте theSprite для событий TextEvent. TEXT_INPUT и чтобы функция textlnputListener ( ) вызывалась и в фазе захвата, и в фазе всплытия. Мы используем следующий код:

theSprite. addEventListener(TextEvent. TEXT_INPUT, textlnputListener, true) theSprite. addEventListener(TextEvent. TEXT_INPUT. textlnputListener, false)

I Если необходимо сделать так, чтобы приемник предка вызывался и в фазе захвата, л щ ив фазе всплытия процесса диспетчеризации события, он должен быть зарегистрирован Щ для этого события дважды.

Регистрация приемника в получателе события

Напомним, что для регистрации приемника получателя для фазы получения уведомления мы устанавливаем параметру useCapture метода addEventListener ( ) значение false, как показано в следующем коде:

получательСобытия. addEventListener(событие, приемник, false)

Таким образом, возвращаясь к нашему текущему сценарию с объектом TextField, чтобы зарегистрировать функцию textlnputListener ( ) вобъекте theTextField для событий TextEvent. TEXT_INPUT, мы используем следующий код:

theTextField. addEventListener(TextEvent. TEXT_INPUT.

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

TextlnputListener, false)

Или просто:

theTextField. addEventListener(TextEvent. TEXT_INPUT, textlnputListener)

Приведенная строка кода заставляет функцию textlnputListener ( ) выполняться всякий раз, когда среда Flash осуществляет диспетчеризацию события TextEvent. TEXT_INPUT, получателем которого является объект theTextField. Функция textlnputListener ( ) выполняется после того, как экземпляр класса Stage и объект theSprite получат уведомления о возникновении события в фазе захвата, но до того, как экземпляр класса Stage и объект theSprite получат уведомления в фазе всплытия.

Двойное назначение параметра useCapture

Как было показано в двух предыдущих разделах, параметру useCapture метода addEventListener ( ) устанавливается значение false в двух различных ситуациях:

? когда регистрируемый приемник предка должен вызываться в фазе всплытия;

? когда регистрируемый приемник получателя должен вызываться в фазе получения.

Следовательно, когда при регистрации приемника для события параметр useCapture установлено значение false, этот приемник будет вызываться в процессе диспетчеризации события, если справедливо любое из следующих условий:

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

? получателем события является потомок объекта, в котором зарегистрирован приемник (в данном случае приемник вызывается на фазе всплытия, после того как потомок обработает это событие).



Полезные ссылки
Случайные записи
  • 23.08.2011">Пиво не только вредно, но и полезно!
  • 03.03.2011">Руководство по actionscript. часть 5, стр. 054
  • 25.02.2011">Руководство по actionscript. часть 6, стр. 088
  • 16.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.27
  • 21.10.2011">Мегафон
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 011
  • 16.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.13
  • 05.03.2011">Руководство по actionscript. часть 5, стр. 010
  • 20.03.2011">Руководство по actionscript. часть 2, стр. 061
  • 14.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.75
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.70
  • 17.06.2012">В Великобритании возобновили расследование по Google Street View
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.62
  • 08.03.2011">Руководство по actionscript. часть 4, стр. 080
  • 02.09.2010">Тенденции развития веб-дизайна.
Опрос

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

View Results

Loading ... Loading ...