[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 을 나타내는 정수가 각각 정의되어 있다.

    

설정

트랙백

댓글