Март 2011

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

Следующий код регистрирует приемник события Event. REMOVED с именем removedListener ( ) в объекте container для события Event. REMOVED:

contaiпег. addEventListener(Event. REMOVED, removedListener);

Теперь удалим потомка из объекта container:

chi1d. removeChi1d(grandchiId)

При выполнении предыдущего кода среда Flash осуществляет диспетчеризацию события Event. REMOVED, получателем которого является объект grandchild, и метод removedListener ( ) вызывается на фазе всплытия.

Далее следующий код удаляет сам объект container из экземпляра класса

Stage:

stage. removeChild(contaiпег)

При выполнении приведенного кода среда Flash осуществляет диспетчеризацию события Event. REMOVED, получателем которого является объект container, и метод removedListener ( ) вызывается на фазе получения.

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

private function removedListener (e:Event):void { // Если этот приемник был вызван на фазе захвата или на фазе всплытия… if (е. eventPhase!= EventPhase. ATJARGET) { // …из контейнера удаляется потомок

traceCa descendant was removed from container: » + e. target); } else {

// …в противном случае контейнер удаляется из своего родителя trace(«contaiпег is about to be removed from its parent: » + DisplayObject(e. target).parent);

}

}

В листинге 20.6 представлены предыдущие примеры кода для событий Event. ADDED и Event. REMOVED в контексте тестового класса ContainmentEventDemo. Мы рассмотрим реальные примеры использования событий контейнеров в двух следующих разделах.

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

Листинг 20.6. Демонстрация событий контейнера

package { import flash. display.*; лщугЪ f \ ash. ем ents.*;

public class ContainmentEventDemo extends Sprite { public function ContainmentEventDemo ( ) { // Создаем объекты Sprite

var container:Sprite = new Sprite( ); var child:Sprite = new Sprite( ); var grandchild:Sprite = new Sprite( );

// Приступаем к приему событий Event. ADDED и Event. REMOVED contai ner. addEventLi stener(Event. ADDED, addedLi stener); contai ner. addEventLi stener(Event. REMOVED, removedLi stener);

// Добавляем объект child в объект container container. addChild(child); // Вызывает метод addedListener( )

// на фазе всплытия

// Добавляем объект grandchild в объект child child. addChild(grandchild); // Вызывает метод addedListener( )

// на фазе всплытия

// Добавляем объект container в экземпляр класса-Stage stage. addChild(container); // Вызывает метод addedListener( )

// на фазе получения

// Удаляем объект grandchild из объекта child child. removeChild(grandchiId) // Вызывает метод removedListener( )

// на фазе всплытия

// Удаляем объект container из экземпляра класса Stage stage. removeChild(container) // Вызывает метод removedListener( )

// на фазе получения

}

// Обрабатывает события Event. ADDED

private function addedListener (e:Event):void {

if (e. eventPhase!= EventPhase. AT_TARGET) { traceCcontainer has a new descendant: » + e. target);

} else {

trace(«container was added to a new parent: » + DisplayObject(e. target).parent);

}

}

// Обрабатывает события Event. REMOVED

private function removedListener (e:Event):void {

if (e. eventPhase 1= EventPhase. ATTARGET) { traceCa descendant was removed from container: » + e. target);

} else {

trace(«container was removed from its parent: » + DisplayObject(e. target).parent);

}

}

}

// В результате выполнения приложения ContainmentEventDemo // выводятся следующие строки:

container has a new descendant: [object Sprite] container has a new descendant: [object Sprite] container was added to a new parent: [object Stage] a descendant was removed from container: [object Sprite] container was removed from its parent: [object Stage]

Реальный пример использования событий контейнера

Теперь, когда известно, как работают события Event. ADDED и Event. REMOVED в теории, рассмотрим, как можно использовать их в реальном приложении. Предположим, что мы создаем класс IconPanel, который управляет визуальным расположением графических значков. Класс IconPanel используется в качестве одной из частей большего оконного компонента в интерфейсе, основанном на оконном представлении. Всякий раз при добавлении нового или удалении существующего значка из объекта IconPanel этот объект исполняет алгоритм по размещению значков. Чтобы определить моменты добавления и удаления дочерних значков, объект IconPanel регистрирует приемники для событий Event. ADDED и Event. REMOVED.

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

В листинге 20.7 представлен код класса IconPanel, который намеренно был упрощен, чтобы продемонстрировать использование событий Event. ADDED и Event. REMOVED. Обратите внимание, что приемники событий Event. ADDED и Event. REMOVED выполняют код по размещению значков только в том случае, когда объект IconPanel приобретает нового или теряет существующего непосредственного ребенка. Код по размещению значков не выполняется в следующих ситуациях:

? когда объект IconPanel приобретает или теряет потомка, который не является непосредственным ребенком;

? если сам объект IconPanel добавляется в родительский контейнер.

Листинг 20.7. Размещение значков в классе IconPanel

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

public class IconPanel extends Sprite { public function IconPanel ( ) { addEventLi stener(Event. ADDED. addedListener); addEventLi stener(Event. REMOVED. removedLi stener);

}

public function updateLayout ( ):void { // Выполняет алгоритм размещения значков (код не приводится)

}

// Обрабатывает события Event. ADDED private function addedListener (e:Event):void { if (DisplayObject(e. target. parent) == e. currentTarget) {

updateLayout( );

// Обрабатывает события Event. REMOVED private function removedListener (e:Event):void { if (DisplayObject(e. target. parent) == e. currentTarget) updateLayout( );

}

}

События ADDED TO STAGE и REMOVED J=ROM_STAGE

Как мы уже знаем из двух приведенных выше разделов, события Event. ADDED и Event. REMOVED возникают, когда экземпляр класса DisplayObject добавляется в экземпляр класса DisplayObjectContainer или удаляется из него. Однако по событиям Event. ADDED и Event. REMOVED нельзя определить, находится данный объект в настоящий момент в списке отображения или нет. Чтобы определить, когда экземпляр класса DisplayObject добавляется в список отображения или удаляется из него, используются события Event. ADDED_TO_STAGE и Event. REMOVED FROM STAGE, которые были добавлены в API отображения, начиная с приложения Flash Player 9.0.28.0.

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

Когда отображаемый объект (или один из его предков) добавляется в список отображения, Flash выполняет диспетчеризацию события Event. ADDED_TO_STAGE, получателем которого является данный объект. С другой стороны, когда отображаемый объект (или один из его предков) удаляется из списка отображения, среда Flash выполняет диспетчеризацию события Event. REMOVED_FROM_STAGE, получателем которого является данный объект.

г*

В отличие от событий Event. ADDED и Event. REMOVED, у событий Event. ADDED_TO_STAGE и Event. REMOVED_FROM_STAGE отсутствует фаза всплытия. Для получения события 3f Event. ADDED_TO_STAGE или Event. REMOVE_FROM_STAGE через предка объекта зарегистрируйте приемник в этом предке для фазы захвата события.

Обобщенный код, который необходим для регистрации приемника события Event. ADDED_TO_STAGE в экземпляре класса DisplayOb j ect, выглядит следующим образом:

отображаемыйОбъект. addEventListener(Event. ADDED_T0_STAGE.

приемникСобытияАс1с1ес1То5Ьаде);

Код, необходимый для приемника события Event. ADDED_TO_STAGE, выглядит таким образом:

private function приемникСобытияАс1с1ес1То5Ьаде (e:Event):void { }

Обобщенный код, который необходим для регистрации приемника события Event. REMOVED_FROM_STAGE в экземпляре класса DisplayObject, выглядит следующим образом:

отображаемыйОбъект. addEventListener(Event. REMOVED_FROM_STAGE,

npHeMHHt Теперь рассмотрим обобщенный код, необходимый для приемника события

Event. REMOVED_FROM_STAGE:

private function npHeMHHKCo6biTHnRemovedFromStage (e:Event):void { }

Отображаемые объекты обычно используют событие Event. ADDED TO STAGE, чтобы убедиться в доступности объекта Stage перед обращением к его методам, переменным или событиям. Предположим, что мы создаем класс CustomMousePointer, который представляет пользовательский указатель мыши. Наш класс CustomMousePointer расширяет класс Sprite, поэтому его экземпляры могут добавляться в список отображения. Мы хотим, чтобы наш класс был зарегистрирован в экземпляре класса Stage для получения событий MouseEvent. MOUSE_EVENT, благодаря чему мы сможем синхронизировать позицию пользовательского указателя мыши с позицией системного указателя мыши.

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

Однако после создания новый объект CustomMousePointer не находится в списке отображения, поэтому не имеет доступа к экземпляру класса Stage и не может зарегистрироваться для получения события MouseEvent. MOUSE MOVE. Вместо этого объект должен ожидать уведомления о том, что он был добавлен в список отображения (через событие Event. ADDEDTOSTAGE). Как только объект CustomMousePointer будет добавлен в список отображения, его переменная stage будет ссылаться на экземпляр класса Stage и он сможет успешно зарегистрироваться для получения события MouseEvent. MOUSE_MOVE. Следующий код демонстрирует соответствующий фрагмент кода, относящийся к событию Event. ADDED_TO_STAGE, из класса CustomMousePointer. Полный листинг кода класса CustomMousePointer можно найти в подразд. «Определение позиции указателя мыши» разд. «События мыши» гл. 22.

package {

public class CustomMousePointer extends Sprite { public function CustomMousePointer ( ) { // Просим сообщить, когда этот объект будет добавлен // в список отображения

addEventListener(Event. ADDED_TO_STAGE, addedToStageListener);

}

// Вызывается, когда этот объект добавляется в список отображения

private function addedToStageLi stener (e: Event) -.void { // Теперь можно безопасно регистрироваться в экземпляре класса Stage // на получение событий MouseEvent. M0USE_M0VE stage. addEventLi stener(MouseEvent. M0USE_M0VE, mouseMoveLi stener);

}

}

}

Собственные события Event. ADDED_TO_STAGE и Event. REMOVE_FROM_ STAGE. Первая версия приложения Flash Player 9 не содержала ни события Event. ADDED_TO_STAGE, ни события Event. REMOVED_FROM_STAGE. Тем не

менее, воспользовавшись обычным интерфейсом API отображения и проявив немного изобретательности, мы можем вручную определить, что данный объект был добавлен в список отображения или удален из него. Для этого мы должны отслеживать состояние предков данного объекта с помощью событий Event. ADDED и Event. REMOVED.

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

? StageDetector. ADDED TO STAGE — когда объект добавляется в список отображения;

? StageDetector. REMOVED_FROM_STAGE — когда объект удаляется из списка отображения.

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

Вы вполне можете применять пользовательские события ADDED TO STAGE и REMOVED_FROM_STAGE, даже не имея ни малейшего представления о том, как устроен и функционирует класс StageDetector. Однако он позволяет провести интересный обзор методик программирования, относящихся к списку отображения, которые были рассмотрены в этой главе, поэтому посмотрим, как он работает.

В классе StageDetector объект, для которого отслеживаются пользовательские события ADDED_TO_STAGE и REMOVED_FROM_STAGE, присваивается переменной watchedRoot. Рассмотрим общий подход, применяемый в классе StageDetector для определения присутствия объекта watchedOb j ect в списке отображения.

? Нужно отслеживать события Event. ADDED и Event. REMOVED для объекта watchedRoot.

? Когда объект watchedRoot добавляется в объект DisplayOb j ectContainer, проверять, находится ли watchedOb j ect в настоящий момент в списке отображения (он находится в списке отображения, если значение его переменной stage не равно null). Если в настоящий момент объект watchedOb j ect находится в списке отображения, то следует выполнить диспетчеризацию события StageDetector. ADDED_TO_STAGE. Если нет, то приступить к отслеживанию событий Event. ADDED и Event. REMOVED для нового объекта watchedRoot. t

? Когда объект watchedOb j ect есть в списке отображения, если watchedRoot или любой из его потомков удаляется из объекта DisplayOb j ectContainer, проверять, является ли удаленный объект предком watchedOb j ect. Если да, то выполнить диспетчеризацию события StageDetector. REMOVED_FROM_STAGE и приступить к отслеживанию событий Event. ADDED и Event. REMOVED для нового корня иерархии отображения объекта watchedOb j ect.

Теперь рассмотрим код класса StageDetector.

Листинг 20.8. Пользовательские события ADDED_TO_STAGE и REMOVED_FROM_STAGE

package { import flash. display.*: import flash. events.*:

// Наблюдает за указанным отображаемым объектом, чтобы определить,

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

// и рассылает соответствующие пользовательские события

// StageDetector. ADDED_TO_STAGE и StageDetector. REMOVED_FROM_STAGE.

// ИСПОЛЬЗОВАНИЕ:

// var StageDetector:StageDetector = new StageDetector(someDisplayObject); // StageDetector. addEventListener(StageDetector. ADDED_TO_STAGE, // addedToStageListenerFunction);

// stageDetector. addEventLi stener(StageDetector. REMOVED_FROM_STAGE, // removedFromStageListenerFunction);

public class StageDetector extends EventDispatcher { // Событийные константы

public static const ADDED_TO_STAGE:String = «ADDED_TO_STAGEH: public static const REMOVED_FROM_STAGE:String = «REMOVED_FROM_STAGE»;

// Объект, для которого будут генерироваться события ADDЕD_TO_STAGЕ // и REMOVED_FROM_STAGE

private var watchedObject:DisplayObject = null:

// Корень иерархии отображения, содержащей объект watchedObject private var watchedRotit.’D'is’f&layObject = null:

// Флаг, который говорит, находится ли объект watchedObject // в настоящий момент в списке отображения private var onstage:Boolean = false:

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

public function StageDetector (objectToWatch:DisplayObject) {

// Приступаем к мониторингу указанного объекта

setWatchedObject(obj ectToWatch); } ‘

// Приступает к мониторингу указанного объекта, чтобы определить,

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

public function setWatchedObject (objectToWatch:DisplayObject):void {

// Сохраняем отслеживаемый объект

watchedObject = objectToWatch:

// Помечает, находится ли объект watchedObject в настоящий момент // в списке отображения if (watchedObject. stage!= null) { onstage = true:

}

// Находит корень иерархии отображения, содержащей объект

// watchedObject, и регистрируем в найденном объекте приемники

// для событий ADDED/REMOVED. Проверяя, добавлен или удален

// корень объекта watchedObject, мы сможем определить,

// находится объект watchedObject в списке отображения или нет.

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

SetWatchedRoot(findWatchedObjectRoot( ));

// Возвращает ссылку на отслеживаемый объект public function getWatchedObj ect ( ):DisplayObject { return watchedObject;

}

// Освобождает ресурсы данного объекта StageDetector. Вызываем этот // метод перед уничтожением объекта StageDetector. public function dispose ( ):void {

clearWatchedRoot( );

watchedObject = null;

}

// Обрабатывает события Event. ADDED, получателем которых является // корневой объект иерархии отображения — объекта watchedObject private function addedListener (e:Event):void { // Если текущий объект watchedRoot был добавлен… if (е. eventPhase == EventPhase. AT_TARGET) { // …проверяем, находится ли объект watchedObject в настоящий // момент в списке отображения if (watchedObject. stage!= null) { // Помечаем, что объект watchedObject теперь находится // в списке отображения onStage = true;

// Сообщаем приемникам, что объект watchedObject теперь

// находится в списке отображения

dispatchEvent(new Event(StageDetector. ADDED_TO_STAGE));

}

// Объект watchedRoot был добавлен в другой контейнер, поэтому // сейчас корнем иерархии отображения объекта, содержащей объект // watchedObject, является новый объект. Находим этот новый корень // и регистрируемся в нем для получения событий ADDED и REMOVED. setWatchedRoot(findWatchedObjectRoot( ));

}

}

// Обрабатывает события Event. REMOVED для корневого объекта иерархии // отображения объекта watchedObject private function removedListener (e;Event):void { // Если объект watchedObject находится в списке отображения… if (onStage) { // …проверяем, был ли удален объект watchedObject // или один из его предков var wasRemoved:Boolean = false; var ancestor;DisplayObject = watchedObject; var target;DisplayObject = DisplayObject(e. target); while (ancestor!= null) { if (target == ancestor) { wasRemoved = true; break;

}

ancestor = ancestor. parent;

// Если объект watchedObject или один из его предков был удален… if (wasRemoved) {

// …регистрируемся для получения событий ADDED и REMOVED

// от удаленного объекта (который является новым корнем

// иерархии отображения объекта watchedObject).

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

SetWatchedRoot(target);

// Помечает, что объект watchedObject больше не находится // в списке отображения onStage = false;

// Сообщаем приемникам, что объект watchedObject был удален // из объекта Stage

dispatchEvent(new Event(StageDetector. REMOVED_FROM_STAGE));

}

}

}

// Возвращает корневой’ объект иерархии отображения, в настоящий момент // содержащий объект watchedObject

private function findWatchedObjectRoot ( );DisplayObject { var watchedObjectRoot:DisplayObject = watchedObject; while (watchedObjectRoot. parent!= null) { watchedObjectRoot = watchedObjectRoot. parent;

}

return watchedObjectRoot;

}

// Начинает отслеживание событий ADDED и REMOVED, получателем // которых является корневой объект иерархии отображения // объекта watchedObject

private function setWatchedRoot (newWatchedRoot.-DisplayObject) :void { clearWatchedRoot( ); watchedRoot = newWatchedRoot; regi sterLi steners(watchedRoot);

}

// Удаляет приемники событий из объекта watchedRoot и ссылку // на объект watchedRoot из данного объекта StageDetector private function clearWatchedRoot ( );void { if (watchedRoot!= null) {

unregi sterLi steners(watchedRoot);

watchedRoot = null;

}

}

// Регистрирует приемники событий ADDED и REMOVED в объекте watchedRoot private function regi sterLi steners (target; DisplayObject)-.void {

target. addEventLi stener(Event. ADDED, addedLi stener);

target. addEventLi stener(Event. REMOVED, removedLi stener);

// Отменяет регистрацию приемников событий ADDED и REMOVED // в объекте watchedRoot

private function unregisterListeners (target:DisplayObject):void { target. removeEventLi stener(Event. ADDED, addedLi stener); target. removeEventLi stener(Event. REMOVED, removedLi stener);

}

}

}

О том, как пользовательские события StageDetector. ADDED_TO_STAGE и Stage. REMOVED_FROM_STAGE применяются в классе CustomMousePointer, будет рассказано в гл. 22.

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

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

Пользовательские графические классы

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

Дополнительную информацию о «коде с погрешностями» (общие признаки потенциальных м?. 4 • проблем в коде) можно найти по адресу http.7/xp. c2.com/CodeSmell. html.

4 дк—

Чтобы обеспечить возможность повторного применения и модульность при работе с примитивными фигурами, мы можем перенести повторяющиеся процедуры рисования в пользовательские классы, которые расширяют класс Shape. Начнем с пользовательского класса Rectangle, применив чрезвычайно простой подход, который предоставляет весьма ограниченный набор вариантов контура и заливки и не позволяет изменять прямоугольник после того, как он будет нарисован (мы расширим возможности класса Rectangle в гл. 25). Этот код продемонстрирован в листинге 20.9.

Листинг 20.9. Rectangle — простой подкласс класса Shape

package { import flash. display. Shape:

public class Rectangle extends Shape { public function Rectangle (w:Number,

h:Number,

lineThickness:Number, lineColor:uint, fillColonuint) { graphi cs.1i neStyle(1i neThi ckness, 1i neColor);

graphics. beginFill(fill Col or. 1); graphics. drawRect(0, 0, w, h);

}

}

}

Поскольку класс Rectangle расширяет класс Shape, он наследует переменную graphics класса Shape и может использовать ее для рисования прямоугольника.

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

Для создания нового экземпляра класса Rectangle применяется следующий знакомый нам код:

var rect:Rectangle = new RectangledOO. 50. 3. OxFFOOOO. OxOOOOFF):

Поскольку класс Shape является потомком DisplayObject, класс Rectangle наследует возможность быть добавленным в список отображения (как и любой другой потомок класса DisplayOb j ect), наподобие следующего кода:

некийКонтейнер. addChi 1 d(rect);

Являясь потомком класса DisplayObject, объект Rectangle может быть позиционирован, повернут и подвергнут другим действиям, как и любой другой отображаемый объект. Например, следующий код устанавливает горизонтальной позиции объекта Rectangle значение 15, а вертикальной — значение 30:

rect. x = 15: rect. у = 30:

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

Листинг 20.10. ClickableHeading — подкласс класса TextField

package { import flash. display.*:

public class ClickableHeading extends TextField { public function ClickableHeading (headText:String. URLString) { html = true:

autoSize = TextFieldAutoSize. LEFT:

htmlText = «» + headText + ««;

border = true:

background = true:

}

}

}

Вот как можно использовать класс ClickableHeading в приложении:

var head.-ClickableHeading = new ClickableHeading(

«Essential ActionScript 3.0″. «http://www. moock. org/eas3″);

addChild(head):

На рис. 20.17 показано результирующее содержимое, отображаемое на экране. При выполнении этого примера в среде Flash текст будет связан с сопутствующим сайтом для этой книги.



Полезные ссылки
Случайные записи
  • 02.03.2011">Руководство по actionscript. часть 5, стр. 093
  • 14.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.60
  • 25.02.2011">Руководство по actionscript. часть 6, стр. 078
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.34
  • 20.03.2011">Руководство по actionscript. часть 2, стр. 060
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 034
  • 12.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.109
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.88
  • 23.02.2011">Руководство по actionscript. часть 7, стр. 030
  • 05.08.2011">Вентиляция помещения необходима для здоровья и продуктивности работников
  • 19.03.2011">Руководство по actionscript. часть 2, стр. 106
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 116
  • 27.08.2010">Советы начинающему дизайнеру.
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 037
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 158
Опрос

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

View Results

Loading ... Loading ...