Stage (сцена) – это фактически первый контейнер в который загружаются все остальные отображаемые объекты, включая root. Stage может быть только один, а вот root может быть сколько угодно, по одному на каждую загруженную внешнюю флешку.
Все отображаемые объекты (
flash.display.DisplayObject) имеют свойства stage и root. До тех пор, пока объект не добавлен на сцену (stage) эти свойства равны null. Свойство stage, когда доступно, всегда ссылается на объект stage. А вот свойство root в разный случаях содержит разные ссылки:
- Для stage, свойство root всегда ссылается на stage
- Для всех объектов, расположенных на главной timeline, свойство root ссылается на главную timeline
- Если объект добавлен прямо на сцену (stage) из любой timeline, свойство root для него и его детей будет ссылаться на stage
- Для объектов расположенных в подгруженном внешнем SWF-файле, свойство root ссылается на главную timeline этого SWF-файла
- Для загруженных картинок, свойство root ссылается на экземпляр класса Bitmap, куда была загружена картинка
Помните, что только после добавления на сцену, или к любому другому объекту уже добавленному на сцену, есть доступ к свойствам stage и root. Это серьезное отличие от ActionScript 1 и 2 и на то есть две причины:
- В AS1 и 2 мувиклипы в момент своего создания уже были добавлены на сцену. В AS3 это не так. Фактически только document class (см. предыдущий совет) изначально расположен на stage (во Flash 9 еще и объекты, расположенные на timeline в IDE до публикации).
- В AS1 и 2 все скрипты и классы были определены внутри timeline или мувиклипов, как результат отовсюду был доступ к свойству _root.В AS3 классы не привязаны к timeline и могут не иметь доступа к root или stage.
Это сильно ограничивает наш доступ к stage или root в скриптах. К примеру, не отображаемый класс в AS3 вообще не может получить доступ к stage или root, только если получит ссылку извне.
Код:
package {
import flash.display.Stage;
public class CustomObject {
private var stage:Stage;
public function CustomObject(stageRef:Stage) {
// Ссылку на stage нужно передавать как параметр конструктора
stage = stageRef;
}
}
}
Отображаемые объекты в момент создания в конструкторе не имеют доступа к stage и root (если только они не были расположены на timeline до компиляции)
Код:
package {
import flash.display.Sprite;
import flash.events.Event;
public class CustomDisplayObject extends Sprite {
public function CustomObject() {
// stage недоступен до тех пор,
// пока объект не будет добавлен на сцену
trace(stage); // null
}
}
}
Это создает определенные трудности. Нужно добавлять дополнительный обработчик события добавления на сцену (ADDED_TO_STAGE), из которого уже вызывать функцию init для совершения необходимых действий.
Другой вариант решения создать статичное свойство в каком-либо классе, в которое прописать ссылку на 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;
}
}
}
Доступ к stage из неотображаемого класса:
Код:
package {
public class RandomClass {
public function RandomClass() {
trace(TopLevel.stage); // [object Stage]
}
}
}
В идеале стоит писать код так, чтобы не было необходимости в создании классов подобных TopLevel и жесткой привязке к нему. Особенно если в разработке участвуют несколько программистов. Определять доступность stage лучше по событию.