ADOBE/ ActionScript

[AS] 플래시 AS3.0 이벤트 관련

AlrepondTech 2020. 9. 21. 18:40
반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

출처: http://cafe.naver.com/shiftouch/book22408/366359

플래시 플레이어 안에서 일어나는 많은 일이 이벤트(event)입니다. 플래시 플레이어 윈도우를 활성화하는 것은 이벤트이고, 마우스를 움직이는 것도 이벤트이고, 버튼을 누르는 것도 이벤트이고, 키보드를 누르는 것도 이벤트이고, 표시 목록에 표시 객체가 추가되는 것도 이벤트이고, 타임라인 재생으로 새 키프레임이 보이는 것도 이벤트이고, 사운드 재생이 끝나는 것도 이벤트입니다. 플래시 플레이어 안에서는 끊임없이 이벤트가 일어납니다. 우리가 할 일은 알맞은 이벤트를 잡아서 알맞은 처리를 하는 것 뿐입니다. 플래시 플레이어 속 상황은 그렇게 하여 흘러갑니다. "이벤트가 주도하는 환경"인 것입니다.

이벤트는 수도 없이 많이 일어나고, 그 중 원하는 이벤트를 잡으려면 이벤트를 분류해야 합니다. 모든 이벤트에는 대상(target)과 유형(type)이 있습니다. 이벤트는 특정 대상에서 일어나며, 일어난 이유에 따라 유형이 다릅니다.

이벤트는 객체입니다. 이벤트를 나타내는 객체의 타입은 Event 클래스 또는 Event 클래스의 하위 클래스입니다. 앞으로 이벤트를 나타내는 객체를 이벤트 객체라고 부르겠습니다. 이벤트 유형은 수없이 많으나 성질이 비슷한 것끼리 묶을 수 있습니다. 마우스 누름, 마우스 뗌, 마우스 움직임 같이 마우스와 관련된 이벤트들은 '마우스 이벤트'로 묶을 수 있고, 키보드 누름, 키보드 뗌과 같이 키보드와 관련된 이벤트들은 '키보드 이벤트'로 묶을 수 있습니다. 그리고 특정 이벤트 클래스의 인스턴스로 특정 분류의 이벤트들을 나타냅니다. (이벤트 클래스 역시 Event 클래스 또는 Event의 하위 클래스들을 통틀어 나타내는 말입니다) 예를 들면 Event의 하위 클래스인 MouseEvent 클래스의 인스턴스로 마우스 이벤트를 나타냅니다. 유형은 Event 클래스의 인스턴스 속성인 type으로 구분하고요. 모든 이벤트를 Event 객체만으로 나타내지 않고 굳이 분류해서 Event 객체 말고도 MouseEvent 객체, KeyboardEvent 객체 등으로 나타내는 이유는 이벤트 유형에 따라 그 이벤트를 나타내는 이벤트 객체로 제공할 정보가 다르기 때문입니다. 마우스 이벤트와 관련된 이벤트 객체에는 마우스의 위치에 대한 정보가 들어 있어야 하지만, 키보드 이벤트 객체에는 그런 정보가 필요 없습니다.

Event 클래스는 이벤트를 위한 기반 클래스이므로 모든 이벤트 처리에 필요할 만한 속성과 메서드가 정의되어 있습니다. 몇 가지 들어 보면, 이벤트의 유형을 알기 위한 type 속성, 이벤트 대상을 알기 위한 target 속성, 다른 일에 쓰기 위해 자신을 복제하는 clone() 메서드가 있습니다.

이벤트 대상 역시 객체입니다. 하지만 모든 객체가 이벤트를 받을 수 있는 것은 아닙니다. EventDispatcher 클래스와 그 하위 클래스들의 인스턴스만 이벤트를 받을 수 있습니다. DisplayObject 클래스는 EventDispatcher 클래스를 상속하기 때문에 모든 표시 객체는 이벤트를 받을 수 있습니다.

이벤트 대상에서 이벤트를 잡으면, 이제 이벤트를 무엇으로 처리하느냐가 문제입니다. 이벤트는 이벤트 수신자 함수, 줄여서 이벤트 수신자, 줄여서 수신자라고 부르는 조금 특별한 함수로 처리합니다. 어느 대상에 어느 이벤트 유형에 대해 어느 함수를 등록하면, 그 대상에서 그 유형의 이벤트가 일어났을 때 그 함수가 호출됩니다. (조금 뒤에서 보겠지만 등록은 EventDispatcher 클래스에 정의된 인스턴스 메서드로 수행합니다) 특별한 함수라고는 하지만 보통 함수를 선언하는 것처럼 하면 됩니다. 다만 매개변수는 하나여야 하고, 매개변수의 타입은 Event 또는 그 하위여야 합니다. 이렇게 나타낼 수 있습니다.

 

function 수신자함수(e:이벤트클래스):void {

처리

}

 

한 대상의 한 이벤트 유형에 대해 수신자를 하나만 등록해야 한다는 법은 없습니다. 같은 이벤트 유형에 대해 여러 수신자를 등록하면 그 대상에서 그 유형의 이벤트가 일어났을 때 그 수신자 모두가 호출됩니다. 한 이벤트 수신자를 한 대상의 한 유형에 대해서만 등록해야 한다는 법도 없습니다. 어느 무비 클립의 마우스 누름에 대해, 다른 버튼의 마우스 움직임에 대해 한 이벤트 수신자를 등록하면 무비 클립을 눌러도, 버튼 위에서 마우스를 움직여도 같은 이벤트 수신자가 호출됩니다.

 

정리하겠습니다. 이벤트를 잡아서 처리하려면 이벤트 객체, 이벤트 대상, 이벤트 수신자가 있어야 합니다. 이벤트 객체의 타입은 Event 또는 Event의 하위 클래스입니다. 이벤트 대상의 타입은 EventDispatcher 클래스 또는 EventDispatcher 클래스의 하위 클래스입니다. 이벤트 수신자는 이벤트 객체를 매개변수로 받는 함수입니다.

 

그러면 이벤트를 잡아서 처리해 봅시다.

 

이벤트_연습.fla 임시 FLA

FLA 파일을 열면 1~5프레임에 숫자가 적혀 있는 무비 클립이 스테이지에 있습니다. 무비 클립의 인스턴스 이름은 mc이고, 위의 버튼은 play_btn, 아래의 버튼은 stop_btn입니다. 만들려는 예제는 재생 버튼을 누르면 무비 클립을 재생하고, 멈춤 버튼을 누르면 무비 클립의 재생을 멈추는 것입니다.

 

먼저 이벤트 대상인 객체에 이벤트 수신자인 함수를 등록하는 방법을 알아야 합니다. EventDispatcher 또는 그 자손의 인스턴스만 이벤트를 받을 수 있다고 했습니다. 이벤트 수신자는 이렇게 등록합니다.

 

대상.addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

  • type 일어나는 것을 감지할 이벤트 유형입니다.
  • listener 그 유형의 이벤트가 발생하면 실행될 이벤트 수신자입니다.
  • useCapture 이벤트의 흐름을 설명할 때 설명하고 지금은 넘어갑니다. (= 오른쪽의 값은 기본값을 뜻합니다)
  • priority 이벤트 수신자가 호출될 순서입니다. 한 이벤트 유형에 대해 여러 수신자를 등록할 수 있기 때문에 수신자들의 호출 순서를 조절할 수 있습니다. = 오른쪽의 값은 기본값을 뜻합니다.
  • useWeakReference 쓰레기 수거와 관련된 매개변수입니다. 보통은 그냥 기본값을 넣으면 됩니다. = 오른쪽의 값은 기본값을 뜻합니다.
  • 반환값 : void

 

지금은 뒤의 세 매개변수를 무시하고 이벤트 유형과 이벤트 수신자에만 신경을 쓰겠습니다.

 

이벤트 유형은 문자열 상수입니다. 예를 들어 '마우스 누름'을 나타내는 이벤트 유형은 글에서는 mouseDown이라고 소개하지만 액션스크립트 코드로는 "mouseDown"이라고 씁니다. 보통은 문자열을 직접 쓰지 않고, 관련된 이벤트 클래스에 정의된 정적 속성을 사용합니다.

 

play_btn.addEventListener(MouseEvent.MOUSE_DOWN, playBtn_mouseDown)

 

MouseEvent 클래스의 정적 상수 MOUSE_DOWN은 문자열 "mouseDown"을 가리킵니다. 문자열 리터럴을 직접 쓰면 오타가 나올 수도 있지만 이렇게 관련된 이벤트 클래스에 정의된 상수를 쓰면 절대 틀릴 염려가 없습니다. ("mouseDOwn"이라고 쓴다면 대상 위에서 마우스를 눌러도 이벤트 수신자는 호출되지 않습니다) 플래시 플레이어가 전달하는 이벤트 객체의 타입에는 그 이벤트 객체가 나타낼 수 있는 유형들을 위한 상수들이 정의되어 있습니다. 예를 들어 mouseDown 유형의 이벤트는 MouseEvent 객체로 표현되므로 MouseEvent 클래스에 문자열 "mouseDown"을 가리키는 상수가 정의되어 있습니다. 그러니까 앞으로는 mouseDown 이벤트 같이 쓰지 않고 MouseEvent.MOUSE_DOWN 이벤트 같이 쓰겠습니다. 문자열을 직접 쓰는 대신 상수를 쓰는 습관을 들이는 게 좋습니다.

 

playBtn_mouseDown이라는 이벤트 수신자를 등록하게 했으므로 playBtn_mouseDown이라는 수신자를 정의합니다. 이벤트 수신자 역시 보통 함수입니다. 이름은 어떻게 지어도 상관 없지만 저는 관련된 이벤트 대상과 이벤트 유형을 알기 쉽게 짓습니다.

 

play_btn.addEventListener(MouseEvent.MOUSE_DOWN, playBtn_mouseDown);

function playBtn_mouseDown(e:MouseEvent):void {

// 수행할 코드

}

 

MouseEvent.MOUSE_DOWN 이벤트는 MouseEvent 객체로 표현되므로 매개변수 e는 MouseEvent 객체를 가리킵니다. 이제 함수 안에 무비 클립을 재생하는 명령만 작성하면 됩니다. 무비 클립은 기본으로 자동으로 재생되니까 멈춤 버튼을 눌러서 무비 클립의 재생이 멈춘 상태에서만 이 버튼을 누르는 것이 의미가 있습니다. 재생을 멈춘 무비 클립을 다시 재생하려면 그 무비 클립의 play 메서드를 호출합니다. play 메서드의 매개변수는 없습니다.

 

play_btn.addEventListener(MouseEvent.MOUSE_DOWN, playBtn_mouseDown);

function playBtn_mouseDown(e:MouseEvent):void {

mc.play();

}

 

마찬가지로 멈춤 버튼의 기능도 구현합니다. 재생을 멈추려면 무비 클립의 stop 메서드를 호출합니다. stop 메서드의 매개변수는 없습니다.

 

stop_btn.addEventListener(MouseEvent.MOUSE_DOWN, stopBtn_mouseDown);

function stopBtn_mouseDown(e:MouseEvent):void {

mc.stop();

}

 

위의 두 코드를 입력하고 실행해서 재생 버튼과 멈춤 버튼을 눌러 보세요. 무비 클립 재생을 멈춘 상태에서 재생 버튼을 누르면 다시 재생되고, 재생되는 상태에서 멈춤 버튼을 누르면 재생이 멈춥니다.

 

무비 클립의 메서드를 두 개 더 알아보겠습니다. gotoAndPlay 메서드로 무비 클립의 재생점을 특정 프레임으로 이동시켜 그 프레임부터 재생하게 할 수 있고, gotoAndStop 메서드로 무비 클립의 재생점을 특정 프레임으로 이동시키고 그 프레임에서 멈추게 할 수 있습니다. 두 함수 모두 매개변수는 동일합니다.

 

무비클립.gotoAndPlay(frame:Object, scene:String = null):void

무비클립.gotoAndStop(frame:Object, scene:String = null):void

  • frame   이동할 프레임의 번호(index) 또는 이름표(label)입니다. 번호는 숫자이고 이름표는 문자열이기 때문에 두 값을 모두 지원하기 위해 매개변수의 타입이 Object입니다.
  • scene   이동할 프레임을 포함하는 장면입니다. 같은 장면에서 프레임만 이동할 거면 입력하지 않아도 됩니다. null은 '아무 것도 아님'을 나타내는 특별한 값입니다.

 

수신자 함수를 등록했으면 등록을 해제할 때도 옵니다. EventDispatcher 객체에서 다음 메서드를 호출하면 됩니다. (EventDispatcher 객체라고는 썼지만, EventDispatcher 클래스와 EventDispatcher 클래스의 하위 클래스들의 인스턴스 모두를 통틀어 말하는 것입니다. 클래스의 속성과 메서드는 하위 클래스로 상속되니까요)

 

removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void

  • type   수신자를 등록한 이벤트 유형입니다. 여러 이벤트 유형에 대해 등록했다가 특정 이벤트 유형에 대해서만 등록을 해제하면 그 이벤트 유형에 대한 등록만 해제됩니다.
  • listener   등록을 해제할 수신자입니다.
  • useCaptrue   addEventListener에서도 넘어갔던 부분입니다. 지금도 넘어가고, 이벤트 흐름 부분에서 설명하겠습니다.

 

지금까지 본 이벤트 객체는 플래시 플레이어가 생성해서 보낸 것입니다. 무비 클립 a를 마우스로 누르면 플래시 플레이어에서 MouseEvent.MOUSE_DOWN 이벤트를 나타내는 MouseEvent 객체를 생성하여 a에 보내는 것이지요. 하지만 우리가 직접 이벤트 객체를 생성하고 이벤트 대상에 보낼 수도 있습니다. EventDispatcher 클래스의 다음 인스턴스 메서드를 봅시다.

 

dispatchEvent(event:Event):Boolean

event  전달할 이벤트 객체입니다.

반환값 : 이벤트 전달이 성공하면 true가 반환되고, 실패하거나 이 이벤트 객체에서 preventDefault 메서드가 호출되면 false가 반환됩니다.

 

Event 객체를 생성하고 EventDispatcher 객체에 보내 보겠습니다. Event 생성자의 구성은 이렇습니다.

 

Event(type:String, bubbles:Boolean = false, cancelable:Boolean = false)

 

다음 코드는 예시입니다.

 

var sp:Sprite = new Sprite();

sp.addEventListener("test", sp_test);

function sp_test(e:Event):void {

trace("이벤트 테스트");

}

 

sp.dispatchEvent(new Event("test"));

 

addEventListener로 sp에서 test 유형의 이벤트가 발생하면 sp_test 함수가 호출되게 하고, dispatchEvent로 sp에 test 유형의 이벤트를 일으켰습니다. 이벤트 객체를 전달했다고도 표현합니다.

 

보통 이벤트를 어느 대상에 전달하면 바로 그 대상에 전달됩니다. 그래서 그 이벤트 유형에 맞는 수신자들이 호출됩니다. 하지만 표시 객체에서는 좀 더 복잡합니다. 표시 객체에 이벤트가 전달될 때, 바로 표시 객체에 전달되는 것이 아니라 이벤트는 표시 목록에서 Stage 객체부터 시작하여 그 표시 객체까지 '타고 내려가고', 그 표시 객체에 '머물고', 다시 Stage 객체로 '솟아 오릅니다'. 차례대로 캡쳐 단계, 대상 단계, 버블링 단계라고 합니다.

 

 이것을 이벤트 흐름이라고 합니다. 이것이 중요한 이유는 자식에서 일어난 이벤트를 부모에서 잡을 수 있기 때문입니다. a가 b를 자식으로 가질 때, a에 test 유형에 대해 수신자를 등록하면 b에서 test 유형의 이벤트가 일어나는 것을 잡을 수 있습니다. 하지만 a.addEventListener("test", 수신자) 처럼 등록하면 b에 대한 이벤트가 캡쳐 단계가 아니라 버블링 단계에서 잡힙니다. addEventListener 메서드의 세 번째 매개변수인 useCapture의 기본값이 false이기 때문입니다. 이 값이 false이면 수신자는 대상 단계와 버블링 단계에서만 작동합니다. true이면 캡쳐 단계에서만 작동합니다. 그러니까 useCapture를 true로, false로 하면 한 대상의 한 유형에 대해 한 수신자를 두 번 등록할 수 있습니다. removeEventListener로 등록을 해제할 때도 useCapture를 따져야 합니다. removeEventListener 메서드에도 세 번째 매개변수로 useCapture가 있습니다.

 

표시 객체에 전달되는 모든 이벤트가 이렇게 이벤트 흐름을 타는 것은 아닙니다. 특정 유형의 이벤트들은 캡쳐 단계, 버블링 단계 없이 대상 단계만 거칩니다. 이런 이벤트는 브로드캐스트 이벤트라고 합니다. enterFrame 이벤트가 그 예입니다. 레퍼런스를 보면 어느 이벤트가 브로드캐스트 이벤트인가를 알 수 있습니다. 그리고 브로드캐스트가 아닌 이벤트에서 주의할 점이 있습니다. 브로드캐스트 이벤트가 아닌 이벤트, 예를 들어 MouseEvent.MOUSE_DOWN 이벤트에 대해 수신자를 등록했다면 그 대상이 표시 목록에서 제거되는 순간 수신자도 자동으로 해제됩니다. removeEventListener를 호출하지 않아도요. 브로드캐스트 이벤트에 대해 등록한 수신자는 그렇지 않습니다.

 

 

 

 

=================================

=================================

=================================

 

 

 

반응형