[AS3] EventDispatcher의 이해

Programming/ActionScript 3.0 2007. 7. 13. 13:09
자료를 찾다가 AS3의 이벤트 모델에 대해 쉽게 설명된 자료가 있어서 내용 추가 및 수정하였다. AS2의 컴포넌트에서 사용했던 EventDispatcher는 AS3에서 모든 표시 오브젝트에서 사용하고 있는 EventDispatcher의 표준이 되었다. AS2에서는 addListener도 사용했으나 AS3에서는 좀더 구체적으로 Event를 dispatch 할 수 있는 EventListener만을 사용하고 있다.

AS3 이벤트 모델 개요
AS3의 이벤트 처리는 AS2의 이벤트처리와 조금 다른 것을 볼 수 있다.

1. 이벤트는 “전파”한다
AS3의 표시 오브젝트 DisplayObject으로부터 발생한 이벤트를 그 이벤트를 받은 오브젝트 뿐만이 아니라 다른 오브젝트에서도 리슨 할 수 있다.

발생한 이벤트(클릭되었다 등)는 상자가 된 오브젝트를 부모로부터 자식에게 자식로부터 부모에게 이벤트가 전해져 가는 모델을 채택하고 있다. 이 개념은 이벤트의 전파(event propagation)라 불린다. 이벤트는 트리 구조 안을 이동하면서 각층(노드)에서 대응하는 리스너가 있을지를 검사하고, 있을 경우에는 그 리스너를 실행하게 된다.

예를 들어, 아래와 같이 상자 구조가 있다고 했을 때 DisplayObject (Sprite)를 생각해 보면, Sprite mc_01의 안에 mc_02 라는 Sprite이 있고 그 안에 mc_03라고 하는 Sprite이 있는 구조로 되어 있다. 여기서 mc_03를 클릭한다고 했을 때 AS2에서는 mc_03에 리스너를 등록할 필요가 있었지만 AS3에서는 mc_03 뿐만이 아니라 mc_02와 mc_01라는 Sprite에 설정한 리스너로 mc_03에서 이벤트를 취급할 수가 있다.

 
[상자 구조 샘플]

이것을 적절히 사용하면 이벤트 처리를 집중화시키는 것이 가능하다 .예를 들면 mc_02 ,mc_03에 공통의 이벤트 처리를 하고 싶은 경우라면 각각의 오브젝트에 이벤트 리스너를 등록할 필요가 없다.

2. 전파의 종류
전파는 아래와 같이 3단계로 분류된다.

1. 캡처-단계
2. 타켓-단계
3. 버블링-단계

이벤트의 전파는 원래 DOM (문서 오브젝트 모델)에 대한 이벤트 모델로서 브라우저에 도입된 것이다. (Netscape의 「이벤트 캡쳐링」모델,  Microsoft의 「이벤트 버블링」모델) W3C에 책정되고 있는 이벤트 모델이나 DOM에 대해서는 더 많은 정보가 필요해서 생략한다. 그러나 그 구현 방법은 ActionScript의 이벤트모델과 매우 유사하기 때문에 간단하게라도 알아 두는 편이 도움이 될 것 같다.

3.  캡쳐-단계
AS3에서 제일 초기에 실행되는 것은 이 캡쳐-단계다. 계층 구조의 오브젝트를 검사(리스너가 있는지를 조사)해 가면서 발생한 이벤트에 대응하는 리스너가 있으면 실행하게 된다. 캡쳐-단계에서의 이벤트는 루트로부터 이벤트가 발생한 타겟을 향해서 전파해 나간다.

위 샐플로 이야기하면 mc_03이라는 무비클립이 클릭되었을 경우 타겟은 mc_01 ,mc_02의 순서로 이벤트의 검사하게 된다. 타겟이 되는 mc_03의 이벤트 검사는 캡쳐-단계에서는 포함되지 않는다.

4.  타겟-단계
두번째로 이벤트의 검사를 하는 것은 타겟 단계이다. 이벤트가 발생한 타겟 자체의 이벤트 리스너를 실행한다. AS2의 관점에서 생각하면 이 타겟 단계만 실행된다고 할 수 있다. ‘

5.  버블링-단계
마지막에 이벤트의 검사를 하는 것은 버블링 단계다. 캡쳐-단계와는 반대로 타겟으로부터 루트를 향해서 전파 해 나간다.

위 샘플로 말하면 mc_03이 클릭되었을 경우 타겟은 mc_02 ,mc_01의 순서로 이벤트의 검사를 한다. 타겟이 되는 mc_03의 이벤트 검사는 버블링 단계에서도 포함되지 않는다.

6.  리스너는 중복 실행되지 않는다
여기서 생각해볼 것은 위에서 캡쳐단계와 버블링단계에서 처럼 리스너가 이중으로 실행된다고 생각할 수 있겠으나 그렇지는 않다. AS3의 캡쳐단계에서 리스너는 디폴트로 무효가 된다. 즉, 실질적으로 타겟으로부터 시작해 루트를 향해서 이벤트가 전파 해 나갈 뿐인 것이다. 물론, 캡쳐단계에서 리스너를 유효하게 할 수도 있지만 그럴 경우에는 버블링 단계에서 리스너가 무효가 된다.
양쪽 모두의 이벤트를 유효하게 할 수도 있다 이는 아래에서 이야기한다.


AS3 이벤트 관련의 클래스, 메소드에 대해
이벤트의 전파를 어떻게 제어하는 지와 관련된 클래스나 메소드에 대해 살펴보면 다음과 같다.

1.  addEventListener 메소드
AS3의 표시 오브젝트인 DisplayObject는 EventDispatcher를 상속하고 있다. 따라서 DisplayObject인 모든 군은 addEventListener 메소드를 사용할 수 있다. 여기서 AS3의 EventDispatcher.addEventListener 의 문장구조를 보면 다음과 같다.
addEventListener(
type:String,
listener:Function,
useCapture:Boolean = false,
priority:int = 0,
useWeakReference:Boolean = false
):void
먼저 기본이 되는 인수 type과 listener에 대해서는 기존 AS2의 EventDispatcher 와 다르지 않다. type 은 이벤트 타입(이벤트의 이름, “click” 등)이다. listener는 리스너 핸들러 함수다. 이벤트가 발생하여 리슨 되었을 때에 실행되는 함수다. 나머지의 인수는 옵션인데 설정하지 않는 경우는 디폴트 값이 적용된다.

useCapture는 캡쳐-단계에 리슨을 실시할지의 Boolean 값이다. 디폴트 값은 false다. useCapture를 true로 설정했을 경우 그 리스너는 캡쳐-단계에 이벤트를 리슨 하게 되지만 반대로 버블링 단계에서는 이벤트를 리슨 하지 않는다.

양쪽 모두 리슨 하는 경우는 useCapture의 값을 true / false로 하는 2개의 이벤트 리스너를 등록할 필요가 있다. 또, 레퍼런스에 의하면 캡쳐 단계에서 이벤트를 리슨 하게 되면 계산 처리의 부하가 커진다고 하니 특별한 이유가 없을 때에는 디폴트 값 false로 해 두는 것이 좋을 것이다.

priority는 우선도를 나타낸다. 수치가 큰 것일 수록 선행 처리된다. priority 값이 같은 경우에는 등록된 순서대로 처리된다. 부의 값도 이용할 수 있으므로, 디폴트값(0)을 기준으로 우선도를 설정할 수 있다. 다만, 우선도의 높은 처리가 완료되고 나서 낮은 처리가 다시 시작되는 것은 아니다..

useWeakReference는 리스너에 의한 참조가 약참조인지 어떤지를 나타내는 Boolean 값이다. 디폴트는 false이고 이는 강참조를 나타낸다. useWeakReference의 값을 true로 했을 경우에는 리스너의 가베지 콜렉터로부터 회피된다. 이에 대한 내용은 전에 작성한 포스트에서 확인할 수 있다.

2.  Event 클래스(오브젝트)
AS2의 EventDispatcher는 리스너에게 건네지는 이벤트 오브젝트와 type 프롭퍼티는 Object형태로 전달되었다. 하지만 AS3에서는 Event 클래스가 준비되어 있고 그것을 확장한 여러 가지 서브 클래스가 있다. 예를 들면 마우스 이벤트용의 MouseEvent 클래스나, 키보드 이벤트용의 KeyboardEvent 클래스 등이다.

KeyboardEvent 이벤트는 조작된 키의 키코드를 가지는 등 각각이 잘 정리되어 있다. Event 클래스를 확장하여 자작의 커스텀 클래스를 만들 수도 있다. 이는 예전 포스트에서 이미 내용을 기술해 놓았다.

3.  Event 클래스의 프롭퍼티
이벤트 오브젝트의 베이스가 되는 Event 클래스의 프롭퍼티를 보면 다음과 같다.

bubbles 프롭퍼티는 그 이벤트가 버블링 할지를 나타내는 Boolean 값이다. 디폴트는 false이고 그 경우 이벤트는 버블링 하지 않는다. MouseEvent 등은 true로 설정되어 있고 버블링 단계도 기능한다. 서브 클래스마다의 bublles 프롭퍼티는 레퍼런스를 참조해야 할 것 같다.

cancelable 프롭퍼티는 이벤트의 디폴트 동작을 캔슬할 수 있을지의 Boolean 값이다. 디폴트 동작의 캔슬에 대해서는 전 포스트에서 기술 한 적이 있다. isDefaultPrevented 프롭퍼티는 캔슬이 끝난 상태인지 어떤지를 보존하는 Boolean 값이 된다.

currentTarget / target 프롭퍼티는 각각 타겟의 참조다. target은 이벤트가 발생한 오브젝트의 참조다. currentTaget은 이벤트가 전파 하고 있을 때 이벤트가 어디에 있는지를 나타낸다. 즉, 오느곳의 오브젝트로 리스너를 검사하고 있는지를 나타내어 그 오브젝트의 참조를 돌려준다. target 프롭퍼티는 하나의 이벤트 오브젝트로 공통이지만 currentTaget 프롭퍼티는 전파 하는 과정에서 변해간다.

eventPhase 프롭퍼티는 이벤트가 어느 단계에 있는지를 나타내는 정수치를 가지고 있다.
1 - 캡쳐-단계
2 – 타겟-단계
3 – 버블링-단계

type 프롭퍼티는 이벤트 타입을 나타내는 String 값이다. 예를 들면 "click" 이나 "mouseOver" 등. addEventListener 의 type 값과 조합된다. 리스너는 이 값을 지정하여 이벤트를 리슨 한다.

4.  이벤트는 타겟 단계 밖에 동작하지 않아?
캡쳐-단계와 버블링 단계가 일어나는 것은 DisplayObject 오브젝트만이다. AS2 같이 표시 되어 있지 않은(표시 리스트에 없다) 오브젝트로부터도 이벤트는 dispatch 된다. 예를 들어 “로드가 완료했다”등이라고 하는 것과 같은 이벤트에 대해서도 dispatch 및 청취자는 같은 구조를 취한다. 이러한 이벤트는 많은 경우 전파 할 필요가 없고 이벤트는 타겟으로 직접 플로우 한다.

5.  이벤트의 전파를 정지한다
Event 클래스에는 stopPropagation / stopImmediatePropagation라고 하는 메소드가 있다. 이것들을 이용하면 이벤트의 전파를 도중 캔슬할 수도 있다. 즉, 리스너 안에서 건네 받는 이벤트 오브젝트를 이용하여 그 이벤트의 전파를 멈출 수 있다.

stopPropagation 메소드는 그 이벤트의 전파 자체는 정지하지만 현재의 노드(검사중의 오브젝트)의 리스너는 모두 처리한다.
stopImmediatePropagation 메소드는 전파도 정지하고 현재의 노드의 다른 리스너도 처리하지 않는다.

6.  이벤트의 디폴트의 동작을 캔슬한다
많은 이벤트에는 이벤트 발생시에 디폴트로 실행하는 동작이 있다. Event 오브젝트의 cancelable 프롭퍼티가 true의 경우에 한해서 Event.preventDefault 메소드를 이용하면 이러한 동작을 캔슬할 수 있다.

아래는 레퍼런스의 내용이다.

「예를 들어, 유저가 텍스트 필드에 문자를 입력했을 경우 디폴트 동작에서는 문자가 텍스트 필드에 표시됩니다. TextEvent.TEXT_INPUT 이벤트의 디폴트 동작은 캔슬하기 위해 preventDefault() 메소드를 사용해 문자를 표시하지 않게 할 수 있습니다.」

7.  이벤트의 dispatch
이벤트의 dispatch는 AS2의 EventDispatcher와 같이 dispatchEvent 메소드를 실행할 뿐이다. 다만, dispatchEvent에 건네주는 인수가 AS2에서는 Object이고 AS3는 Event 오브젝트라는 것이 다르다.
새로 Event 오브젝트를 만들고 dispatchEvent의 인수로 건네주게 된다.

Event오브젝트의 constructor는 다음과 같은 문장구조를 갖는다.
Event(event_type:String, bubbles:Boolean, cancelable:Boolean)
bubbles 와 cancelable은 옵션으로 생략 할 수 있다. 간단한 dispatchEvent는 아래와 같다.

my_obj.dispatchEvent(new Event(MouseEvent.CLICK));


    

설정

트랙백

댓글

[AS3] custom 이벤트의 기본적인 dispatchEvent 사용

Programming/ActionScript 3.0 2007. 7. 7. 23:05
Event 클래스를 확장하면 자신의 커스텀 이벤트 클래스를 정의할 수 있다. 예를 들면 아래와 같은 경우다.
















package{
import flash.events.Event;
public class CustomEvent extends Event{
public function CustomEvent(){
super("customEvent");
}
public override function clone():Event{
return new CustomEvent();
}
}
}

(Event의 서브 클래스로 상속할 때는 clone() 메소드를 오버라이드할 필요가 있다.)

EventDispatcher 클래스의 dispatchEvent() 메소드를 사용하면 자동으로 이벤트의 dispatch가 생긴다. 예를 들면 Sprite는 EventDispatcher의 서브 클래스이기 때문에 다음과 같이 CustomEvent을 dispatch 할 수 있다.
package{
import flash.display.Sprite;
public class CustomEventSprite extends Sprite{
public function dispatchCustomEvent():void{
dispatchEvent(new CustomEvent());
}
}
}

그리고는 이벤트 처리를 호출하기 위해 이벤트 리스너를 등록하면 된다.
package{
import flash.display.Sprite;
public class EventTest extends Sprite{
public function EventTest(){
var ceSprite:CustomEventSprite = new CustomEventSprite();
ceSprite.addEventListener("customEvent", onCustomEvent);
ceSprite.dispatchCustomEvent();
}
private function onCustomEvent(evt:CustomEvent):void{
trace("dispatch CustomEvent");
}
}
}

하지만 AS3에서는 다중 상속이 허용되지 않기 때문에 모든 클래스를 EventDispatcher의 서브 클래스로 만들 수 있는 것이 아니다. 상속하고 있는 클래스의 경우에는 IEventDispatcher 인터페이스를 사용한다. 클래스 내부에서 EventDispatcher의 인스턴스를 가져와서 처리를 Delegate하는 방법이다.

    

설정

트랙백

댓글

[AS3] 이벤트 오브젝트

Programming/ActionScript 3.0 2007. 6. 16. 23:10
ActionScript 3.0의 새로운 이벤트 처리 시스템에 있는 이벤트 오브젝트는 2 개의 용도로 사용된다. 하나는 구체적인 개개의 이벤트를 표현해 해당 이벤트에 관한 정보를 각종 프롭퍼티에 적용하는 것이고 다른 하나는 각종 메소드를 사용하여 이벤트 오브젝트를 조작해 이벤트 처리 시스템의 동작을 변화시키는 것이다.

그러한 프롭퍼티와 메소드에 액세스 하기 쉽게 Flash Player API 에 있는 모든 오브젝트는 이벤트 오브젝트가 기본 클래스로 정의되어 있다. Event 클래스는 모든 이벤트 오브젝트에 공통되는 기본적인 프롭퍼티와 메소드를 갖추고 있다.

우선 Event 클래스의 프롭퍼티와 Event 클래스의 메소드에 대해 설명하고 마지막으로 Event 클래스에 서브 클래스가 존재하는 이유에 대해 알아보면 다음과 같다.

Event 클래스의 프롭퍼티
Event 클래스에는 이벤트 오브젝트에 관한 중요한 정보를 제공하는 다수의 읽기전용 프롭퍼티와 정수가 있다. 다음의 프롭퍼티는 특히 중요하다.

이벤트 오브젝트의 타입은 정수에 의해서 나타내져 Event.type 프롭퍼티에 적용된다.
이벤트의 디폴트 동작을 캔슬할 수 있을지 없을지를 Boolean 값에 의해서 나타내져 Event.cancelable 프롭퍼티에 넣게 된다.

디폴트 동작
이벤트에 응답하는 코드는 개발자가 기술하지 않으면 안 되는 것이 대부분이지만 이벤트에 대해서 어떠한 정해진 동작이 명확한 경우에는 일반적인 처리가 Flash Player에 의해서 자동적으로 실행되는 것들이 있다. (개발자가 이 동작을 캔슬하기 위한 코드를 기술했을 경우를 제외한다). Flash Player 에 의해서 자동적으로 실행되는 동작을 디폴트 동작이라고 부른다.

예를 들어, 유저에 의해서 TextField 오브젝트에 텍스트가 입력되었을 때 대부분의 경우는 입력된 텍스트를 그 TextField 오브젝트에 표시할 필요가 있다. 이것은 매우 일반적인 동작이므로 Flash Player 에 이미 정해진 동작이다. 이 동작이 불필요한 경우는 새로운 이벤트 처리 시스템을 사용해 디폴트 동작을 캔슬할 수 있다. 유저에 의해서 TextField 오브젝트에 텍스트가 입력되면 그 입력을 나타내는 행동은 TextEvent 클래스의 인스턴스가 Flash Player에 의해서 작성된다. 입력 텍스트가 Flash Player에 의해서 TextField 오브젝트내에 표시되는 것을 막으려면 그 특정의 TextEvent 인스턴스에 액세스하여 preventDefault() 메소드를 호출하여 처리할 수 있다..

디폴트 동작안에는 캔슬할 수 없는 것도 있다. 예를 들어, 유저에 의해서 TextField 오브젝트내의 단어가 더블 클릭 되면 Flash Player로부터 MouseEvent 오브젝트를 생성하게 된다. 이 경우의 디폴트 동작인 커서 위치에 있는 단어를 하이라이트 하는 처리는 개발자가 임의로 막을 수 없다.

디폴트 동작은 Flash Player로부터 송출되는 이벤트 오브젝트밖에 관련지을 수 없기 때문에ActionScript 의 프로그램으로 송출한 이벤트 오브젝트에 대해서는 실행되지 않는다. 이 점을 이해해 두는 것은 중요한데 예를 들어, EventDispatcher 클래스의 메소드를 사용해 textInput 타입의 이벤트 오브젝트를 송출할 수 있지만 그 경우는 이벤트 오브젝트에 디폴트 동작을 관련지을 수 없다. 따라서 프로그램으로부터 textInput 이벤트를 송출해도 그 결과를 Flash Player 에 의해서 TextField 오브젝트에 문자로 표시될 수는 없다.

이벤트 오브젝트의 타입
모든 이벤트 오브젝트에는 각각 이벤트 타입이 설정된다. 이벤트 타입은 스트링으로서 Event.type 프롭퍼티에 포함된다. 코드로 이벤트 오브젝트의 타입을 알 수 있으면 타입에 따라 오브젝트의 처리 방법을 구별할 수 있어 편리다. 예를 들어, 다음의 코드에서는 myDisplayObject 에게 건네지는 마우스 클릭의 이벤트 오브젝트 모두에 대해서 clickHandler() 청취자 함수가 응답하도록 지정하고 있다.

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);
Event 클래스 자체에 관련된 이벤트 타입의 수는 20 종류를 넘는다. Event 클래스 정의로부터 발췌한 일부 코드는 다음과 같다.

package flash.events
{
public class Event
{
// 클래스 정수
public static const ACTIVATE:String = "activate";
public static const ADDED:String = "added";
// 그 외의 정수는 생략
}
}
이러한 정수를 사용하면 특정의 이벤트 타입을 간단하게 참조할 수 있다. 각 정수가 나타내는 스트링을 직접 사용하는 것은 피하고 정수명으로 참조하는 것이 좋다. 코드에 입력한 정수명에 스펠링 미스가 있었을 경우는 컴파일러에 의해서 검출할 수 있으나 스트링의 값에 스펠링 미스가 있었을 경우는 컴파일시의 에러가 되지 않고 실행시에 예기치 않은 동작이 생겨서 곤란한 디버그 작업이 필요할 가능성이 있다. 예를 들어, 이벤트 청취자를 등록할 때는 다음과 같은 코드를 사용하는 것이 좋다.

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);
다음의 코드는 추천하지 않는 방법이다.

myDisplayObject.addEventListener("click", clickHandler);

디폴트 동작의 캔슬
코드로 cancelable 프롭퍼티를 조사하면 특정의 이벤트 오브젝트에 대한 디폴트 동작을 캔슬할 수 있을지를 알 수 있다. cancelable 프롭퍼티의 값은 Boolean 형태로 디폴트 동작에 대한 캔슬 가부를 나타낸다. 디폴트 동작의 캔슬이 가능한 이벤트는 소수이지만 해당하는 경우는 관련된 동작을 preventDefault() 메소드로 무효화할 수 있다.

이벤트 플로우 정보
Event 클래스의 다른 프롭퍼티에는 다음에 나타내는 것과 같이 이벤트 오브젝트 자체나 이벤트 플로우와의 관계에 관한 중요한 정보가 포함되어 있다.

bubbles : 그 이벤트 오브젝트의 전달 경로가 되는 이벤트 플로우의 구성요소에 관한 정보를 포함한다.
eventPhase  : 이벤트 플로우가 현재 어느 단계에 있는지를 나타낸다.
target : 이벤트 타겟의 참조.
currentTarget  : 해당 이벤트 오브젝트를 현재 처리하고 있는 표시 리스트 오브젝트의 참조.

bubbles 프롭퍼티
이벤트 오브젝트가 bubbling 단계에 있을 때(플로우의 역순으로 전달되는 상태)  그 오브젝트에 의해서 나타내지는 이벤트는 타겟 노드로부터 스테이지로 계층의 상위를 향해 돌아오는 도중에 있다. Event.bubbles 프롭퍼티에는 그 이벤트 오브젝트가 bubbling 단계를 경유할지를 나타낸다. Bubbling의 대상이 되는 이벤트는 반드시 캡쳐 단계와 타겟 단계의 대상이므로 이벤트 플로우의 3 단계 모두를 거치게 된다.이 프롭퍼티의 값이 true 의 경우 해당 이벤트 오브젝트는 3 개의 단계를 모두 경유한 것이고 값이 false 의 경우 해당 이벤트 오브젝트는 bubbling 단계를 경유하지 않은 것이다.

eventPhase 프롭퍼티
eventPhase 프롭퍼티를 조사하면 그 이벤트 오브젝트가 이벤트의 어느 단계에 있는지를 알수 있다. eventPhase 프롭퍼티에는 이벤트 플로우의 3 개의 단계 어느 쪽이든 나타내는 부호없는 정수치가 적용된다. 다음에 나타내는 코드의 발췌처럼 Flash Player API 에는 그러한 부호없는 정수치에 대응한다.  EventPhase 클래스는 flash.events 패키지에서 별도로 정의되어 있다.

package flash.events
{
public final class EventPhase
{
public static const CAPTURING_PHASE:uint = 1;
public static const AT_TARGET:uint = 2;
public static const BUBBLING_PHASE:uint = 3;
}
}
이러한 정수는 eventPhase 프롭퍼티에 대해 유효한 3 개의 값에 대응한다. 정수를 사용하면 코드의 읽기가 쉬워진다. 예를 들어, 이벤트 오브젝트가 타겟 단계에 있는 경우만 myFunc()라는 함수를 호출하도록 하려면 다음과 같은 코드로 조건을 판단할 수 있다.

if (e.eventPhase == EventPhase.AT_TARGET) {
myFunc();
}
target 프롭퍼티
target 프롭퍼티에는 해당 이벤트의 타겟인 오브젝트에 의해 참조가 적용된다. 타겟의 취급은 단순한 경우와 그렇지 않은 경우가 있다. 예를 들어, 마이크가 액티브하게 된 것을 나타내는 이벤트에서는 이벤트 오브젝트의 타겟은 Microphone 오브젝트인 것이 명확하지만 타겟이 표시 리스트내에 있는 경우는 표시 리스트의 계층 구조를 고려할 필요가 있다. 예를 들어, 복수의 표시 리스트 오브젝트가 서로 겹치는 지점이 유저에 의해서 마우스로 클릭되었을 경우 Flash Player는 스테이지로부터 가장 먼 계층에 있는 오브젝트가 이벤트 타겟으로서 선택된다. 그 형태는 다음과 같은 코드로 설명될 수 있다.

parent_mc.child_mc.addEventListener(MouseEvent.CLICK, childClickHandler);
parent_mc.addEventListener(MouseEvent.CLICK, parentClickHandler);

parent_mc.child_mc.buttonMode = parent_mc.buttonMode = true;

function childClickHandler(evt:Event):void{
trace(evt.target.name +" is a child");
}
function parentClickHandler(evt:Event):void{
trace(evt.target.name +" is a parent");
}

출력 :
child_mc is a child
child_mc is a parent

복잡한 SWF 파일에서는 target 프롭퍼티가 잘 기능하지 않는 것이 있다. 각 버튼에 대해서 오브젝트를 사용한 정형적인 수식 처리가 이루어지고 있는 경우는 target 프롭퍼티의 참조처가 버튼이 아니고 수식용의 오브젝트가 되어 버리는 상황이 발생할 수 있다. 이러한 상황에서는 버튼에 이벤트 청취자를 등록해 currentTarget 프롭퍼티를 사용하는 것이 일반적이다. 그렇게 하면 target 프롭퍼티가 상위 오브젝트를 참조하는 경우에도 currentTarget 프롭퍼티로 버튼을 참조할 수 있다.

currentTarget 프롭퍼티
currentTarget 프롭퍼티에는 해당 이벤트 오브젝트를 현재 처리하고 있는 표시 리스트 오브젝트로 참조할 수 있다. 조사하는 대상의 이벤트 오브젝트가 현재 어느 노드로 처리되고 있을지가 사전에 모른다는, 어떻게 보면 이상한 상황같이 들리지만 실제는 자주 일어나는 일이다. 왜냐하면 해당 이벤트 오브젝트의 이벤트 플로우에 포함되는 임의의 표시 오브젝트에 청취자 함수가 등록되어 있을 가능성이 있고 청취자 함수 자체가 임의의 장소에 배치될 가능성이 있기 때문이다. 게다가 1 depths 청취자 함수가 복수의 표시 오브젝트에 등록되어 있는 경우도 있을 수 있다. 프로젝트의 규모가 커져 복잡한 상황에 따라서 currentTarget 프롭퍼티의 유용성은 매우 높아진다.

parent_mc.child_mc.addEventListener(MouseEvent.CLICK, childClickHandler);
parent_mc.addEventListener(MouseEvent.CLICK, parentClickHandler);

parent_mc.child_mc.buttonMode = parent_mc.buttonMode = true;

function childClickHandler(evt:Event):void{
trace(evt.currentTarget.name +" is a child");
}
function parentClickHandler(evt:Event):void{
trace(evt.currentTarget.name +" is a parent");
}

출력 :
child_mc is a child
parent_mc is a parent



Event 클래스의 메소드
Event 클래스의 메소드는 다음의 3 종류로 구별할 수 있다.

유틸리티 메소드 : 이벤트 오브젝트의 카피를 작성하거나 스트링으로 변환한다.
이벤트 플로우 메소드 : 이벤트 오브젝트를 이벤트 플로우로부터 삭제한다.
디폴트 동작 메소드 : 디폴트 동작을 취소하거나 취소가 끝난 상태인지 어떤지를 확인한다.
 

Event 클래스의 유틸리티 메소드
Event 클래스에는 2 개의 유틸리티 메소드가 있다. clone() 메소드는 이벤트 오브젝트의 카피를 작성한다. toString() 메소드는 이벤트 오브젝트의 각종 프롭퍼티와 그러한 값을 나타내는 스트링을 생성한다. 어느 메소드도 이벤트 모델 시스템의 내부에서 사용되고 있는 것이지만 어플리케이션 개발자에게도 일반 용도 전용으로 공개되고 있다.

상급 개발자가 Event 클래스의 서브 클래스를 작성하는 경우에는 이벤트 서브 클래스를 정상적으로 기능시키기 위해서 양쪽 모두의 유틸리티 메소드를 오버라이드(override)하여 독자적인 버젼을 만들 필요가 있다.

Event 클래스의 이벤트 플로우 메소드

이벤트 오브젝트가 이벤트 플로우로 처리되는 것을 정지하려면 Event.stopPropogation() 메소드 또는 Event.stopImmediatePropogation() 메소드를 호출한다. 이것들 2 개의 메소드는 거의 같지만 현재의 노드에 등록되어 있는 나머지의 이벤트 청취자에 대해 실행을 허가할지 하지 않을지라는  점만이 다르다.

Event.stopPropogation() 메소드를 호출하면 해당 이벤트 오브젝트가 이벤트 플로우로 다음의 노드에 전달되는 것을 막을 수 있지만 현재의 노드에 등록되어 있는 이벤트 청취자는 모두 실행된다.
Event.stopImmediatePropogation() 메소드를 호출하면 해당 이벤트 오브젝트가 이벤트 플로우로 다음의 노드에 전달되는 것을 막아, 현재의 노드에 등록되어 있는 다른 이벤트 청취자의 실행도 막을 수 있다.
어느 메소드를 호출했을 경우도 이벤트에 관련되는 디폴트 동작이 실행할지 안할지에 영향을 주지 않는다. 디폴트 동작을 캔슬하려면 Event 클래스의 디폴트 동작 메소드를 별도로 사용할 필요가 있다.

Event 클래스의 디폴트 동작 메소드
디폴트 동작의 취소에 관해서는 preventDefault() 메소드와 isDefaultPrevented() 메소드의 2 개가 있다. preventDefault() 메소드를 사용하면 이벤트에 관련지을 수 있었던 디폴트 동작을 캔슬할 수 있다. 이미 preventDefault()를 호출했는지를 확인하려면 isDefaultPrevented() 메소드를 사용한다.호출이 끝난 경우는 반환값으로서 true를 보내고 아직 호출하지 않은 경우는 false를 돌려준다.

preventDefault() 메소드는 디폴트 동작의 캔슬이 가능한 이벤트에 대해서만 사용할 수 있다. 캔슬의 가부에 대해서는 API 문서로 해당하는 이벤트 타입의 항목을 참조하거나 ActionScript로 해당 이벤트 오브젝트의 cancelable 프롭퍼티를 확인해야 한다.

디폴트 동작을 캔슬해도 이벤트 플로우에 의한 이벤트 오브젝트 처리의 진행에는 영향을 주지 않는다. 이벤트 오브젝트를 이벤트 플로우로부터 없애려면 이벤트 플로우 메소드를 사용할 필요가 있다.

Event 클래스의 서브 클래스

많은 이벤트는 Event 클래스에 정의되고 있는 공통의 프롭퍼티 세트를 사용하면 충분히 표현할 수 있지만 Event 클래스의 프롭퍼티에서는 표현할 수 없는 독특한 성질을 가진 이벤트도 있다. 그러한 이벤트를 위해서 Flash Player API 에는 Event 클래스의 서브 클래스가 몇 개 정의되어 있다.

각 서브 클래스에는 그 이벤트의 카테고리에 특유의 프롭퍼티 및 이벤트 타입이 추가되어 있다. .예를 들어, 마우스의 입력에 관한 이벤트에는 Event 클래스에서 표현할 수 없는 독특한 성질이 있다. MouseEvent 클래스는 Event 클래스를 확장하여 마우스 이벤트의 발생 위치나 발생시에 특정의 키가 밀리고 있었는지등의 정보를 수반하는 프롭퍼티를 추가한 것이다.

또, Event 의 서브 클래스에는 해당 서브 클래스에 이벤트 타입을 나타내는 정수가 포함된다. 예를 들어 MouseEvent 클래스의 경우 마우스 관련의 이벤트 타입이다 click ,doubleClick ,mouseDown ,mouseUp 을 나타내는 정수가 각각 정의되어 있다.

    

설정

트랙백

댓글