27. [junior] DisplayObject. Управление списком отображения (addChild/removeChild)

junior – серия статей для начинающих ActionScript-разработчиков.
Все статьи серии:
http://flashpress.ru/blog/category/junior/

Список отображения(Display list) это то, что мы с вами видим когда смотрим на флешку. Не важно как вы добавляете объект на сцену, используя методы addChild или вы просто нарисовали круг прямо на кадре в редакторе Adobe Flash Professional. Все визуальные объекты попадают в один список отображения. Разница лишь в том что у всех объектов разная глубина отображения. Объект у которого значение глубины больше, отображается выше и перекрывает объекты с меньшим значением глубины. Нумирация глубин объектов начинается с 0.

DisplayObject и его потомки

Отобразить на экране можно только объекты классов которые являются потомками класса DisplayObject. По сути все что вы видите на экране во флешке – это потомки класса DisplayObject. У этого класс очень много потомков, вот некоторые из них: Sprite, MovieClip, TextField, Video…. На картинке ниже можно увидеть всю иерархию подклассов класса DisplayObject:

DisplayObject

  – Классы которые можно создать в коде ActionScript
  – Классы которые создаются только в редакторе Flash
  – Классы которые самому ни как нельзя создать

Зачем нужны классы которые нельзя создать?

Пожалуй самый особенный класс из всех потомков DisplayObject это AVM1Movie. Если ваше приложение написано на ActionScript3, и вы попытаетесь загрузить флешку написанную на ActionScript2, то вы получите объект класса AVM1Movie в свойстве Loader.content. Вы не сможете обратится к внутренним объектам загруженной флешки AS2, но вы можете поместить его куда угодно, т.к. он является наследником класса DisplayObject.

Stage нельзя создать потому что он создается автоматически и один раз в момент инициализации флешь приложения. В одной флешке всегда существует только 1 объект Stage. Что бы получить ссылку на Stage у всех объектов DisplayObject есть свойство stage.

Обратие внимание что свойство stage доступно только после того как вы добавили объект в список отображения с помощью метода addChild. Добавить в список отображения – это значит что все родительские объекты по иерархии должны быть добавлены с помощью метода addChild.

Рассмотрим код:

В конструкторе stage может быть доступен только в том случае если объект является главным классом приложения. Если вы загружаете флешкку – то у всех классов в загружаемой флешке stage не доступен в конструкторе, потому что когда инициализируется консрутктор объект еще не добавлен в список отображения. Обращаться к свойству stage лучше всего после события Event.ADDED_TO_STAGE:

 

Остальные же объекты которые нельзя создать – являются абстрактными классами. Они нужны для того что бы определить базовую функциональность для других разных классов. Например класс InteractiveObject содержит методы и события которые необходимы для работы с мышкой, и наследниками этого класса являются такие визуальные объекты как TextField, Sprite, MovieClip … Что бы лучше понять смысл абстрактных классов давай рассмотрим пример из реального мира: Рассмотрим понятие Ноутбук, он имеет различные отличительные характеристики, например Маленький размер, Открывающийся экран. Но ведь для покупки компьютера не достаточно этих характеристик. Поэтому мы покупаем не Ноутбук а более конкретное устройство: Acer, HP, MacBook и другие. Т.е. в данном случае Ноутбук это понятие абстрактное и оно является базовым для таких понятий как Acer, HP, MacBook (просьба не рассматривать в этом скрытую рекламу, и не спрашивайте меня каким ноутом я пользуюсь :) ).

Bitmap и Shape

Если вы нарисовали что либо на кадре в редакторе Flash Professional, в список отображения кладется экземпляр класса Shape. Картинка размещения на кадре кладется в виде Bitmap. Если же вы положили на stage картинку и выбрали пункт меню Modify->Break Apart (Ctrl+B), то Bitmap уже не создается. Вместо Bitmap рисуется картинка в graphics. Т.е. картинка рисуется программно и результат получится таким же, если бы вы нарисовали картинку прямо в Shape.

Будьте осторожны! Если ваше приложение использует анимацию растеризованных объектов Bitmap или Shape, это может существенно снизить FPS. Вопросам оптимизации приложения будет посвящена отдельная статья, следите за новостями

InteractiveObject

InteractiveObject – это абстрактный класс, и является базовым для всех классов которые могут реагировать на события мыши. Т.е. эти(и только эти) объекты могут генерировать события

  • MouseEvent.MOUSE_CLICK
  • MouseEvent.MOUSE_MOVE
  • MouseEvent.MOUSE_DOWN
  • MouseEvent.MOUSE_OVER
  • и др

Также подклассы класса InteractiveObject имеют некоторые свойства, не доступные другим классам, например:

  • contextMenu
  • mouseEnabled
  • tabEnabled / tabIndex

DisplayObjectContainer

Все визуальные объекты которые могут содержать в себе другие визуальные объекты, являются потомками класса DisplayObjectContainer. К ним относятся классы:

  • Sprite
  • MovieClip
  • Stage

Внутри каждого DisplayObjectContainer существует свой порядок глубин и начинается он с 0. Т.е. если например вы положили на Stage объект container:DisplayObjectContainer, а сверху обычный Bitmap(картинку), то все объекты помещенные внутрь объекта container(с помощью addChild) будут лежать ниже чем объекта Bitmap. Объект добавленный в контейнер называется дочерним по отношению к контейнеру, а сам контейнер является родителем.

Для управления визуальными объектами в списке отображения у объектов потомков DisplayObjectContainer есть свойства:

  • numChildren – количество детей
  • mouseChildren – определяет будут ли дочерние объекты доступны мышке. Подробно про mouseEnabled и mouseChildren можно почитать в статье
  • tabChildren – определяет могут ли дети реагировать на нажатие Tab. Скоро будет статья посвященная табуляции во флешке, следите за новостями ))

Методы доступные для DisplayObjectContainer:

  • addChild(child:DIsplayObject):DisplayObject – добавить дочерний элемент
  • addChildAt(child:DisplayObject, index:int):DisplayObject – добавить дочерний элемент на определенную глубину. Если на этой глубине уже есть другой объект – он и все остальные выше лежащие сдвигаются так что бы не было пустой глубины
  • contains(child:DIsplayObject):Boolean – проверяет является ли объект child дочерним, т.е. лежит ли он в этом контейнере
  • getChildAt(index:int):DisplayObject – получить дочерний объект лежащий на определенной глубине
  • getChildByName(name:String):DisplayObject – получить дочерний объект по имени заданному в свойстве myClip.name
  • getChildIndex(child:DisplayObject):int – узнать глубину дочернего объекта
  • removeChild(child:DisplayObject):DisplayObject – удаляет дочерний элемент из контейнера
  • removeChildAt(index:int):DisplayObject – удаляет дочерний элемент из заданной глубины
  • setChildIndex(child:DisplayObject, index:int):void – изменить глубину дочернего объекта. При смене глубины одного объекта, остальные сдвигаются так что бы не было пустой глубины
  • swapChildren(child1:DisplayObject, child2:DisplayObject):void – поменять местами дочерние объекты.
  • swapChildrenAt(index1:int, index2:int):void – поменять местами дочерние объекты по заданным глубинам

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

Да прeбудет с вами Flash.
Serious Sam
Эту статью прочитали 2873 раз

Возникли вопросы по статье? Не стесняйтесь спрашивать в комментариях или любым другим способом на странице Контакты .

Присоединяйтесь к нам в социальных сетях: ВКонтакте , Twitter и Facebook
Понравилась статья? Буду благодарен если вы поделитесь ссылкой с друзьями:


Комментарии ВКонтакте:




Комментарии Facebook:




Комментарии WordPress:


  1. slavara

    “Обратие внимание что свойство stage доступно только после того как вы добавили объект в список отображения с помощью метода addChild”

    это, грубо говоря, так, если только parent будет добавлен на сцену, а что если нет? вот вам пример, для наглядности:
    var s1:sprite = new Sprite()
    var s2:sprite = new Sprite();
    s2.addChild(s1);

    “Будьте осторожны! Если ваше приложение использует анимацию растеризованных объектов Bitmap или Shape, это может существенно снизить FPS. Вопросам оптимизации приложения будет посвящена отдельная статья, следите за новостями”
    Наверное, поэтому то все и используют кешерованные растеризованные анимации, векторная графика рендерится в разы дольше.

    “contains(child:DIsplayObject):Boolean – проверяет является ли объект child дочерним, т.е. лежит ли он в этом контейнере”
    в каком-то роде вы правы, но не совсем.
    пример:
    var s1:Sprite = new Sprite();
    var s2:Sprite = new Sprite();
    var s3:Sprite = new Sprite();

    s1.addChild(s2);
    s2.addChild(s3);
    trace(s1.contains(s3));//true, но s3 не является дитем s1

    “setChildIndex(child:DisplayObject, index:int):void – изменить глубину дочернего объекта. При смене глубины одного объекта, остальные сдвигаются так что бы не было пустой глубины”
    и опять формулировка не верна!

    1. Serious Sam Автор записи

      1. Добавление в список отображения по определению подразумевает то что все parent-ы по иерархии добавлены через метод addChild

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

      3. На эту тему можно долго спорить, ибо великий русский язык позволят трактовать все что угодно как угодно. Слово дочерний может подразумевать как непосредственную принадлежность, так и через других детей-посредников. Но если посмотреть на официальную документацию Adobe, то можно заметить: contains – Определяет, является ли указанный объект отображения дочерним объектом экземпляра DisplayObjectContainer

      4. Опять во всем виноват русский язык. В следующий раз постараюсь писать более подробно :)

  2. Serious Sam Автор записи

    кстати на счет первого пункта – начинающий разработчик может не понять смысла словосочетания “Список отображения”. Пожалуй я допишу вашу заметку в статью :) спасибо

  3. slavara

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

    1. Serious Sam Автор записи

      по первому пункту я уже писал что Добавление в список отображения по определению подразумевает что все паренты добавлены, я обновил статью что бы у начинающего разработчика не возникало вопросов, за наводку спасибо. По остальным вопросам я не совсем с вами согласен. Конструктивная дискуссия приветствуется :) Не зря ведь говорят что в спорах рождается истина