![]() |
|
||||||||||
|
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В предыдущем примере показано как определить добавление и удаление объекта от другого отображаемого объекта. Но если с экрана будет удален наш родительский объект, то события ADDED/ REMOVED не сработают. Как же отследить реальное добавление или удаление с экрана? Можно воспользоваться классом StageDetection (com.senocular.events.StageDetection)
package com.senocular.events {
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
/**
* StageDetection
* Позволяет DisplayObject реагировать на добавление и удаление со stage
*
* Использовать в конструкторе
* var stageDetect:StageDetection = new StageDetection(this);
* stageDetect.addEventListener(StageDetection.ADDED_TO_STAGE, addedToStage);
* stageDetect.addEventListener(StageDetection.REMOVED_FROM_STAGE, removedFromStage);
*/
public class StageDetection extends EventDispatcher {
protected var target:DisplayObject;
protected var parents:Dictionary;
protected var detect:String;
public static const ADDED_TO_STAGE:String = "addedToStage";
public static const REMOVED_FROM_STAGE:String = "removedFromStage";
/**
* Конструктор
*/
public function StageDetection(targetObject:DisplayObject) {
target = targetObject;
// Определяем за чем нужно следить, за добавлением или удалением
detect = (target.stage == null) ? Event.ADDED : Event.REMOVED;
// Обновляем слушателей у родителей
updateListeners();
}
/**
* Обновляет слушателей событий ADDED и REMOVED
*/
protected function updateListeners(newDetect:String = null):void {
// Очищаем старые listeners у родителей
if (parents) {
for (var key:Object in parents) {
key.removeEventListener(detect, stageCheck, false);
}
}
// Запомним на какие события подписываемся
if (newDetect) detect = newDetect;
// Прописывает слушателей этого события у родителей
parents = new Dictionary(true);
var parent:DisplayObject = target;
while (parent) {
parent.addEventListener(detect, stageCheck, false, 0, true);
parents[parent] = true;
parent = parent.parent;
}
}
/**
* В обработчике ADDED и REMOVED проверяем наличие stage
*/
protected function stageCheck(evt:Event):void {
// Реагируем только на оригинальный источник события
if (evt.target != evt.currentTarget) return;
// evt.type или ADDED или REMOVED
switch(evt.type) {
// Кого-то из родителей добавили к другому объекту
case Event.ADDED:
// stage доступен, значит нас добавили на экран
if (target.stage != null) {
// Рассылаем событие и обновляем listeners
dispatchEvent(new Event(ADDED_TO_STAGE));
updateListeners(Event.REMOVED);
// stage недоступен, значит просто добавили к другому объекту
} else {
// Список родителей изменился, значит обновим listeners
updateListeners();
}
break;
// Родителя удалили со stage
case Event.REMOVED:
// Рассылаем событие и обновляем listeners
dispatchEvent(new Event(REMOVED_FROM_STAGE));
updateListeners(Event.ADDED);
break;
}
}
}
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 для отображаемых объектов добавлены три фазы распространения событий:
1. захват (capturing) Событие начинается со stage и спускается вниз, вызывая обработчики связанные с этим событием у всех объектов (если же обработчика не существует, ничего не происходит). event +---------|----+ | parent | | | +------V-+ | | |child | | | | | | | +--------+ | +--------------+ На стадии обработки вызывается обработчик события объекта которому собственно оно и предназначалось. +--------------+ | parent | | +------ -+ | | |child | | | |event X | | | +--------+ | +--------------+ Перебираются все объекты, начиная с "виновника" события и до stage. +---------^----+ | parent | | | +------|-+ | | |child | | | | | event| | | | +--------+ | +--------------+ Если вы хотите реагировать на стадию захвата (1), необходимо в addEventListener указать третьим параметром true. При этом обработчик события будет реагировать только на стадию захвата. Если вы хотите подписать обработчик события на все стадии нужно вызвать addEventListener дважды: |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Если нужно пресечь дальнейшее распространение события можно использовать методы stopPropagation() (flash.events.Event.stopPropagation()) или stopImmediatePropagation() (flash.events.Event.stopImmediatePropagation()).
stopPropagation – предотвращает дальнейшее распространение события в стадии захвата (capturing) или подъема (bubbling) stopImmediatePropagation – блокирует вообще все, в том числе и фазу обработка (targeting). Смотрим пример: var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.CLICK, clickCircle1);
circle.addEventListener(MouseEvent.CLICK, clickCircle2);
stage.addEventListener(MouseEvent.CLICK, clickStage);
function clickCircle1(evt:MouseEvent):void {
// evt.stopPropagation();
// evt.stopImmediatePropagation();
trace("clickCircle1");
}
function clickCircle2(evt:MouseEvent):void {
trace("clickCircle2");
}
function clickStage(evt:MouseEvent):void {
trace("clickStage");
}
Срабатывают два обработчика событий на клик мышки "clickCircle1","clickCircle2" фаза обработка (targeting) и обработчик "clickStage" на фазе подъема (bubbling). Если убрать комментарий с evt.stopPropagation(); В обработчике "clickCircle1" вызывается stopPropagation, которое предотвращает дальнейшее распространение события по фазам захвата (capturing) и подъема (bubbling), поэтому далее нормально вызывается обработчик "clickCircle2" в фазе обработка (targeting), но не вызывается "clickStage", поскольку он уже на фазе подъема (bubbling). Если убрать комментарий с evt.stopImmediatePropagation(); В этом случае не будет вызван даже обработчик "clickCircle2" в фазе обработка (targeting). |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Stage (сцена) – это фактически первый контейнер в который загружаются все остальные отображаемые объекты, включая root. Stage может быть только один, а вот root может быть сколько угодно, по одному на каждую загруженную внешнюю флешку.
Все отображаемые объекты (flash.display.DisplayObject) имеют свойства stage и root. До тех пор, пока объект не добавлен на сцену (stage) эти свойства равны null. Свойство stage, когда доступно, всегда ссылается на объект stage. А вот свойство root в разный случаях содержит разные ссылки:
package {
import flash.display.Stage;
public class CustomObject {
private var stage:Stage;
public function CustomObject(stageRef:Stage) {
// Ссылку на stage нужно передавать как параметр конструктора
stage = stageRef;
}
}
}
package {
import flash.display.Sprite;
import flash.events.Event;
public class CustomDisplayObject extends Sprite {
public function CustomObject() {
// stage недоступен до тех пор,
// пока объект не будет добавлен на сцену
trace(stage); // null
}
}
}
Другой вариант решения создать статичное свойство в каком-либо классе, в которое прописать ссылку на root или stage и уже к этому свойству обращаться из любого места. Лучше всего для этого подойдет document class, т.к. он изначально имеет доступ к stage и сам является root. Пример: package {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Stage;
public class TopLevel extends MovieClip {
public static var stage:Stage;
public static var root:DisplayObject;
public function TopLevel() {
TopLevel.stage = this.stage;
TopLevel.root = this;
}
}
}
В идеале стоит писать код так, чтобы не было необходимости в создании классов подобных TopLevel и жесткой привязке к нему. Особенно если в разработке участвуют несколько программистов. Определять доступность stage лучше по событию. |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Если вы используете MXMLC (компилятор из Flex 2 SDK) для компиляции ActionScript 3 SWFs, вы можете использовать SWF metadata tag для назначения свойств флешки. Всего можно установить 4 свойства:
После компиляции будет создан SWF размером 500x450 с белым фоном и частотой кадров 24. |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 добавлен новый класс Proxy (flash.utils.Proxy) для замены методов addProperty и __resolve из ActionScript 1 и 2.
Proxy классы обычно используются для создания набора переменных с гибкими возможностями (например, Flex классы ArrayCollection, ListCollectionView, XMLListCollection). Proxy класс более детально будет рассмотрен в следующих советах |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
В ActionScript 3 добавлен новый оператор in (in operator), который используется для проверки наличия свойства в объекте. Это аналогично hasOwnProperty, но работает и для унаследованных свойств.
Так же оператор in можно использовать для проверки правильности номера индекса в массиве: |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Методы getProperty и setProperty используются для управления необъявленными свойствами класса. Если какое-то свойство явно не объявлено в классе, то при попытке прочитать его значение, будет вызван метод getProperty. Аналогично при записи вызывается метод setProperty.
Как и все методы класса Proxy, getProperty и setProperty объявлены в пространстве имен «flash_proxy» (flash.utils.flash_proxy), чтобы не возникало конфликтов с публичными методами. Для переопределения этих методов в своем классе обязательно нужно указывать пространство имен flash_proxy. Пример: класс CustomObject наследуется от Proxy и переопределяет методы getProperty и setProperty для управления динамическими свойствами. package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic public class CustomObject extends Proxy {
public var classProperty:String = "classProperty"; // объявленное свойство
private var customProperties:Object = new Object(); // хранилище динамических свойств
public function CustomObject() {
}
// Вызывается при чтении динамического свойства
override flash_proxy function getProperty(name:*):* {
if (name in customProperties) {
return customProperties[name];
}
return "Property does not exist";
}
// Вызывается при записи в динамическое свойство
override flash_proxy function setProperty(name:*, value:*):void {
customProperties[name] = "Property "+name+": "+value;
}
}
}
|
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
Во Flash 9, когда вы размещаете MovieClip на сцене (timeline) с указанием имени (instance name), автоматически происходят сразу два действия:
1. Вы присваиваете методу «name» этого мувиклипа строку эквивалентную instance name. 2. Вы создаете переменную в timeline с именем аналогичным instance name мувиклипа со ссылкой на этот мувиклип. Флеш делает все это самостоятельно при компиляции SWF файла, чтобы помочь вам управлять мувиклипами на сцене. Важно понимать, что при создании мувиклипами средствами ActionScript, эти действия не выполняются автоматически. К примеру: // Здесь «my_mc» это instance name мувиклипа на сцене trace(my_mc); // [object MovieClip] trace(my_mc.name); // my_mc // Создаем мувиклип с помощью AS и добавляем его к my_mc var another_mc:MovieClip = new MovieClip(); another_mc.name = "child_mc"; my_mc.addChild(another_mc); // Переменная для доступа к созданному мувиклипу // автоматически не создается в my_mc trace(another_mc); // [object MovieClip] trace(my_mc.child_mc); // undefined trace(my_mc.another_mc); // undefined MerlinTwi: В дополнение к примеру стоит отметить, что поскольку любой мувиклип размещенный на timeline является динамическим, то можно просто создать в нем новое свойство ссылающееся на созданный мувиклип. // Создаем мувиклип с помощью AS и добавляем его к my_mc var another_mc:MovieClip = new MovieClip(); another_mc.name = "child_mc"; my_mc.addChild(another_mc); // создаем в my_mc новое свойство «another_mc» для ссылки на новый мувиклип my_mc.another_mc = another_mc; // проверяем trace(my_mc.another_mc); // [object MovieClip] |
|
|||||
|
Регистрация: Oct 2003
Адрес: Москва
Сообщений: 328
|
ActionScript 3 позволяет определять константы, для этого используется ключевое слово const (const keyword), которое записывается вместо var (var keyword). Обычно константы записывают большими буквами, разделяя слова подчеркиванием, например, Event.ENTER_FRAME это константа.
Пример объявления константы: package {
import flash.display.Sprite;
public class MyClass extends Sprite {
public const MY_CONSTANT:String = "constant";
public function MyClass () {
}
}
}
|
![]() |
![]() |
Часовой пояс GMT +4, время: 03:45. |
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | |
| Опции просмотра | |
|
|