[AS3] DisplayObject란

Programming/ActionScript 3.0 2007. 7. 20. 11:10
1. DisplayObject란 무엇인가?
AS2까지는 MovieClip이 모든 것을 처리할 수 있었으나 AS3에서는 기존의 MovieClip의 기능을 여러 개의 클래스로 분산해 놓았다.

1.1. 표시 오브젝트란

표시 오브젝트란 화면에 표시되는 모든 오브젝트라고 할 수 있다. 예를 들면 AS2의 MovieClip도 화면에 표시되므로 표시 오브젝트라고 할 수 있다. String 이나 Sound와 같은 클래스의 오브젝트는 그 자체로 화면에 표시할 수 없는 것들이기 때문에 표시 오브젝트라고 할 수 없다.

AS3에서는 MovieClip을 복수의 클래스에 분산시켰는데 타임 라인 기능이 없는 Sprite과 같이 MovieClip보다 적은 기능을 갖고 있는 클래스도 있고 비트 맵을 표현하는 Bitmap 클래스, 텍스트를 표시하는 TextField 클래스 등이 있다. Sprite와 같은 클래스를 이용하면 MovieClip을 사용하는 것보다는 전체적으로 퍼포먼스를 향상 시킬 수 있다. 이유는 AS3이전에는 MovieClip 자체에서 거의 모든 기능을 포함하고 있었기 때문에 MovieClip 하나만을 보더라도 묵직했지만 그것을 기능별로 분류하여 오브젝트 자체가 가벼워 졌기 때문이다. 실제로 사용하게 되는 표시 오브젝트 클래스들은 아래와 같은 클래스들이 있다.

AVM1Movie, Bitmap, MorphShape, Shape, StaticText, Video, SimpleButton, TextField, Loader, Sprite, Stage, MovieClip

1.2. 표시 오브젝트 컨테이너란

표시 오브젝트는 “화면에 표시되는 모든 오브젝트” 라고 하였지만 정확하게는 “화면에 표시할 수 있는 모든 오브젝트” 라고 할 수 있다.

new로 만든 표시 오브젝트만으로 화면에 표시되지는 않는다. 표시 오브젝트는 표시 오브젝트 컨테이너에 넣어야만 화면에 표시된다. 아래에서 이야기 하겠지만 표시 오브젝트 컨테이너에 있는 addChild나 addChildAt 메소드 등을 이용해서 컨테이너에 표시 오브젝트를 추가하는 행위로서 화면에 표시된다. 표시 오브젝트 컨테이너가 될 수 있는 클래스는 아래와 같은 클래스들이다.

Loader, Sprite, Stage, MovieClip

여기서 표시 오브젝트 컨테이너는 그 자체가 표시 오브젝트라는 것을 알 수 있다.
AS3의 이전 버전에서 사용하던MovieClip이 상자 구조를 취할 수 있던 것처럼 이러한 클래스도 상자 구조를 취할 수 있다.

1.3. 표시 리스트란
이와 같이 컨테이너 화면에 표시되고 있는 오브젝트의 리스트를 표시 리스트라고 한다. swf 1개의 최상위에는 1개의 Stage 오브젝트가 있다. 이것이 스테이지의 최상위 컨테이너가 된다.

스테이지로부터 표시 오브젝트는 트리 구조를 갖게 되며 컨테이너가 될 수 없는 표시 오브젝트는 리프 노드(그 이상 분기하지 않는 것)이며
컨테이너는 리프 노드, 또는 브랜치 노드(그 이상 분기 가능한)가 된다.

1.4. 표시 오브젝트의 실체
표시 오브젝트는 보통 변수 같아서 하나의 표시 오브젝트의 실체는 오로지 하나다. 표시 오브젝트를 복수의 컨테이너에 addChild 할 수 없으며 동일 컨테이너에 addChild 했을 경우에도 컨테이너에서는 한 번 삭제되어(이동했다는 표현이 더 적절하겠다) 컨테이너의 맨 위(depth)에 추가된다. 표시 오브젝트 컨테이너에는 addChild와 반대의 기능을 하는removeChild라는 메소드를 가지고 있다. 이것은 이름대로 컨테이너로부터 표시 오브젝트를 삭제하는 메소드다. removeChild 메소드는 컨테이너(표시 리스트)로부터 지정한 표시 오브젝트를 제외할 뿐, 메모리에서 제거되는 것이 아니라는 것을 잊어서는 안 된다. 표시 오브젝트를 더 이상 사용하지 않을 경우에는 removeChild와 함께 별도로 delete 연산자로 표시 오브젝트를 삭제하여야만 가비지 컬렉터에 의해 메모리 회수 대상이 될 수 있다.

2. DisplayObject 클래스와 DisplayObjectContainer 클래스의 관계

표시 오브젝트의 개념을 토대로 표시 오브젝트의 기본이 되는 2개의 클래스를 보면서 좀 더 구체적으로 이야기하면 다음과 같다.

2.1. DisplayObject 클래스 개략
모든 표시 오브젝트는 DisplayObject 클래스를 상속하고 있다.(자세한 상속 관계는 레퍼런스를 참조) 간단하게 말하면 모든 표시 오브젝트에 공통의 성질(프롭퍼티나 메소드)은 DisplayObject 형을 갖고 있는 것이다. 예를 들면 x 나 y ,height ,alpha 등은 공통 항목으로서 DisplayObject 클래스가 가지고 있는 것이다.

MovieClip을 잘 다루기 위해서 레퍼런스를 보는 경우 AS2 까지는 MovieClip만을 보면 되었으나 AS3부터는 기본이 되는 DisplayObject의 프롭퍼티와 메소드를 알아 둘 필요가 있다. 반대로 말하면 DisplayObject의 취급을 알아 두면 모든 표시 오브젝트를 컨트롤 할 수 있다. (DisplayObject 속성에 한하여) 레퍼런스를 참조할 때는 DsplayObject의 항목을 우선적으로 확인해 볼 필요가 있다. DisplayObject 자체는 표시를 위한 기능을 가지고 있지 않으므로 사용자 클래스를 만드는 경우는 DisplayObject의 서브 클래스를 확장하여 사용하면 된다.

2.2. DisplayObjectContainer 클래스 개략
Sprite나 MovieClip은 컨테이너가 될 수 있다고 이야기 했는데 그것들은 DisplayObjectContainer 클래스를 상속하고 있기 때문이다. 컨테이너를 조작하는 메소드나 프롭퍼티(addChild등)는 DisplayObjectContainer 클래스가 공통으로 가지고 있는 기능이다. 물론 DisplayObjectContainer 클래스는 DisplayObject 클래스를 상속하고 있다.
「심도」의 취급에 대해서도 DisplayObjectContainer (프롭퍼티•메소드)로 관리하게 된다. Sprite나 MovieClip을 취급하는 경우는 이러한 클래스 레퍼런스를 참조할 필요가 있다.

2.3. AS3에서의 심도 관리는 어떻게 되나
AS3 이전의 액션스크립트에서는 depth나 getNextHighestDepth을 자주 사용하였지만AS3에서는 이러한 메소드는 사라졌다. 하지만「심도」와 같은 개념은 남아 있는데, AS3에서는 해당 컨테이너가 몇 번째에 위치해 있는가를 나타낼 때 “인덱스 위치” 라는 개념으로 설명할 수 있다.

인덱스 위치는 0에서 부터 시작해 증가하는데 0은 가장 안쪽(아래)이 되며 수치가 큰 만큼 앞(위)에 표시된다.

인덱스 위치는 기존에 사용하던 심도의 개념처럼 고정된 것이 아니다. 컨테이너 내에서 표시 오브젝트가 추가되거나 위치가 조정 되면 다른 자식 오브젝트도 자동적으로 인덱스 위치가 조정된다. 심도와는 달리 인덱스 위치는 불연속적인 성격을 가지지 않으며 절대적으로 연속적이다.
만약 0, 1,2라는 인덱스 위치를 가지고 있는 3개의 오브젝트가 하나의 컨테이너 안에 있을 경우 인덱스 1에 있는 오브젝트를 인덱스 0으로 이동할 경우 AS3 이전의 스크립트에서는 0 뎁스 위치에 있는 오브젝트가 삭제되고 1뎁스에 있는 오브젝트가 0뎁스로 이동하고 기존의 1뎁스는 소멸하면서 중간에 1뎁스에는 오브젝트를 갖고 있지 않은 불연속적인 성격을 갖고 있었으나 AS3부터는 인덱스 1위치를 0위치로 이동할 경우 자동적으로 0위치에 있던 오브젝트는 인덱스 1위치로 이동하게 되므로써 연속적인 위치를 유지하게 된다.

2.4. 컨테이너의 조작
좀 더 구체적으로 이야기 하기 위해서 DisplayObjectContainer의 메소드나 프롭퍼티를 몇 개 소개하면 다음과 같다. (자세한 것은 레퍼런스 참조)

•addChild / addChildAt 메소드
컨테이너에 표시 오브젝트를 추가한다. addChild는 항상 맨 위에 자식 오브젝트를 추가한다.(인덱스 위치의 마지막) addChildAt을 사용하면 특정 인덱스 위치를 지정할 수 있다.

•setChildIndex / swapChildren / swapChildrenAt 메소드
컨테이너의 자식 오브젝트의 인덱스 위치를 변경한다. swapChildren, swapChildrenAt은 2개의 자식 오브젝트를 지정하고 위치를 바꾼다. 전자는 인수로서 2개의 오브젝트를 지정하고 후자는 2개의 인덱스 위치를 지정해서 바꿀 수 있다.

•removeChild / removeChildAt 메소드
컨테이너로부터 표시 오브젝트를 삭제한다. removeChild는 직접 오브젝트를 삭제하고(표시 리스트에서 제거)  removeChildAt은 인덱스 위치를 통해 삭제한다. 표시 오브젝트의 실체는 삭제되지 않으며 어디까지나 컨테이너로부터 제거될 뿐이다.(메모리 영역은 유지된다.)

•getChildAt / getChildByName 메소드
지정한 오브젝트를 돌려준다. getChildAt은 인덱스 위치를 통해 돌려주고 getChildByName은 오브젝트명을 통해서 지정한 오브젝트를 돌려준다. getChildByName의 경우는 해시검색을 진행하기 때문에 getChildAt 쪽이 getChildByName보다 처리속도가 빠르다.

•getChildIndex 메소드
지정한 오브젝트의 인덱스 위치를 돌려준다.

•contains 메소드
컨테이너 내에 지정한 오브젝트가 있을지를 조사하여 Boolean 값(true/false)를 돌려준다.
import flash.display.Sprite;
var sprite1:Sprite = new Sprite();
var sprite2:Sprite = new Sprite();
var sprite3:Sprite = new Sprite();
var sprite4:Sprite = new Sprite();

sprite1.addChild(sprite2);
sprite2.addChild(sprite3);

trace(sprite1.contains(sprite1)); // true
trace(sprite1.contains(sprite2)); // true
trace(sprite1.contains(sprite3)); // true
trace(sprite1.contains(sprite4)); // false
•numChildren 프롭퍼티
컨테이너에 포함되는 자식 오브젝트의 수를 돌려준다. (컨테이너명.numChildren - 1)로 하면 컨테이너의 맨 위의 인덱스 위치를 지정할 수 있다.

    

설정

트랙백

댓글