본문 바로가기

동강의AS3.0 강좌

[Basic] 12강 Event.... Event... Event...


디자인을 하다가 Flash 를 시작하시는 분이나, 일반 프로그래밍을 하다가 시작하는 분이나, Actionscript 의 이벤트라는 개념은 생소하게 다가 옵니다. 그래서 시작하는 분들이 조금이라도 빨리 이해를 돕고자 Event... 에 대해 이야기를 해 보겠습니다.  

Actionscript 3.0 을 시작하고 적응하기 어려웠던 점은 2.0 과 다르게 브로드 케스팅으로 이벤트를 호출하고 호출 받는 다는 점이었습니다. 2.0 에서도 그러한 개념이 있긴 했지만, 3.0 에 와서는 완전 바뀌었습니다.  

가장 많이 사용하는 flash.events.Event  = Event
flash.events.MouseEvent = MouseEvent  

초기에 Event 는 ENTER_FRAME 을 돌리기 위한 이벤트로 많이 사용되고 MouseEvent 는 마우스의 각기 반응들에 이벤트를 걸어 주기 위해 사용 됩니다. 그렇다면 어떠한 원리로 이벤트가 걸리게 되는 걸까요? ( 개념을 정리 하기 위한 추상적인 클래스이니, 고칠 부분을 알려 주시기 바람니다. )  

우선 Mouse 라는 Class 가 존재 합니다.

Mouse 라는 클래스 안에는 마우스의 상태가 MOUSE_OVER ,MOUSE_OUT, CLICK 되었을때의 호출되는 함수(여기에서는 각각의 문을 함수라고 생각하시면 됩니다 ) 가 정의 되어 있습니다. 이 세개의 문들은 마우스 이벤트가 일어날때를 대비 해서 항상 기다리고 있지요. (addEventLister 로 이벤트가 걸렸을 경우에만 기다리고 있습니다. )

이 문이 열리는 것이 마우스 이벤트가 실행 되었다는 의미 입니다. Actionscript 에서는 이 문들을 대기 시키기 위해서  

addEventListener(MouseEvent...)
의 방법으로 이벤트를 대기 목록에 하나하나씩 추가 하게 됩니다. 이벤트를 대기 하는 메모리 공간에 자신이 추가 하고 싶은 이벤트 를 추가(add) 하는 것이지요. 반대로 이 이벤트 대기 목록에서 빼기 위한 방법으로  removeEventLister(MouseEvent...) 의 방법을 사용함니다. 더이상 이벤트가 발생하는걸 기다리지 않아도 된다는 의미 입니다.  

하지만 위의 Mouse class 에 있는 각각의 문들이 열렸다는 것은 어떻게 알수 있을까요? 내부적으로 마우스가 클릭되거나 Over 되거나 했을때 자동적으로 문이 열리기 되는 것일까요? 내부적으로 그렇게 구현되었을 수도 있겠지만, Actionscript 에서는 이벤트를 발생시키고 생성하는 매소드를 제공합니다.  이때 사용 하는 것이 dispatchEvent 입니다.  

 
dispatchEvent () 메서드  
public override function dispatchEvent(event:Event):Boolean

언어 버전 :  ActionScript 3.0
Player 버전 :  Flash Player 9

이벤트를 이벤트 흐름으로 전달합니다. 이벤트 대상은 dispatchEvent() 메서드가 호출된 EventDispatcher 객체입니다.

매개 변수

event:Event — 이벤트 흐름으로 전달된 Event 객체입니다. 이벤트를 다시 전달하는 경우, 해당 이벤트의 복제본이 자동으로 만들어집니다. 이벤트가 전달된 뒤에는 이벤트의 target 속성을 변경할 수 없으므로, 재전달에 성공하려면 이벤트의 복사본을 새로 만들어야 합니다.

반환값
Boolean — 이벤트가 성공적으로 전달된 경우 값은 true입니다. false 값은 실패를 나타내거나 해당 이벤트에서 preventDefault()가 호출되었음을 나타냅니다.

오류
SecurityError — Stage 객체의 dispatchEvent() 메서드를 호출하면 스테이지 소유자(기본 SWF 파일)와 다른 보안 샌드박스에 있는 호출자에 대해 예외가 발생합니다. 스테이지 소유자는 이와 같은 상황을 피하기 위해 Security.allowDomain() 메서드 또는 Security.allowInsecureDomain() 메서드를 호출하여 호출자 도메인에 권한을 부여할 수 있습니다. 자세한 내용은 ActionScript 3.0 프로그래밍의 "보안" 장을 참조하십시오.

 중요한건 알겠는데 어떻게 사용 되는 것인가? Actionscript 에서는 내부적으로 Mouse 가 CLICK 되었을때 발생하는 함수가 구현되어 있을것입니다. 만약 MouseCLICK 이 발생할때 실행 되는 함수가 Class Mouse 의 function CLICK ():void {} 이라면 dispatchEvent 를 사용해서 연결 시킬수 있습니다.

 

 flash.events.MouseEvent
 
  1. package flash.events{
  2.        
  3.         public class MouseEvent
  4.         {
  5.                 public static const MOUSE_OVER:String = "mouseover";
  6.                 public static const MOUSE_OUT:String = "mouseout";
  7.                 public static const CLICK:String = "click";
  8.                
  9.                 etc....
  10.                
  11.                 public function MouseEvent(type : String, bubbles : Boolean = false, cancelable : Boolean = false)
  12.                 {
  13.                         ........
  14.                        
  15.                 }
  16.                
  17.                
  18.         }
  19. }
  20.  

 

Mouse Class 안에 존재 하는 CLICK 매소드 , 이 매소드는 마우스가 클릭되면 호출된다. 하지만 이벤트를 발생 시키는

담당은 dispatchEvent 가 맡게 된다. 

 

public function CLICK():void
{

  ........................

  .......................... dispatchEvent 로 이벤트와 함수를 연결시켜주는 것 외에 다른것들도 구현되어 있을것 같습니다.
 dispatchEvent(new MouseEvent(MouseEvent.CLICK));

}

 

dispatchEvent 로 인해 CLICK 이라는 함수와 MouseEvent 의 CLICK 이라는 이벤트는 동기화가 되게 됩니다. CLICK 함수가 실행되면 '아 MouseEvent.CLICK 이벤트가 실행 되었구나 ' 하고 리스너들이 알게 되는 것입니다.

 Flash 에서의 이벤트 전달과 캐취는 이런식으로 발생하게 됩니다. 이러한 것들은 이미 Actionscript 에서 내부적으로 구현 되어 있는 것들이고, 이 원리를 이용하여 CustomEvent 를 만들수 있고, 이벤트를 좀더 유도리 있게 사용할수 있게 되는 것입니다.   

간단한 예로 마이크에서 나오는 소리를 1초 단위로 받기 위한 이벤트를 만들어 보겠습니다. 우선 SoundEvent 란 CustomEvent 를 생성하고, flash.events.Event 를 상속 받았습니다.

 

  1. package customEvent {
  2.  import flash.events.Event;
  3.  
  4.  /**
  5.   * @author dongkang
  6.  
  7.   */
  8.  public class SoundEvent extends Event {
  9.  
  10.   public static const CATCH:String = "catching";
  11.  
  12.   public function SoundEvent(type : String, bubbles : Boolean = false, cancelable : Boolean = false) {
  13.    super(type, bubbles, cancelable);
  14.   }
  15.  }
  16. }

 

이렇게 하는 것 만으로도 자신만의 커스텀 이벤트가 생성됩니다. FDT 나 Flex Builder 를 사용하시는 분들은 Event 를 상속 받는 클래스를 생성했을때 자동으로 인자값이 들어 가는것을 확인할수 있을 것입니다. 그리고 SoundEvent 의 속성으로 사용될 public static const CATCH:String = "catching"; 를 생성하였습니다. CATCH 는 SoundEvent.CATCH 와 같이 사용될 수 있는 것이고 catching 은 addEventListener("catching',함수); 와 같이 사용할수 있게 합니다. 하지만 위의 SoundEvent Class 만으로는 동작이 불가능합니다. 어떠한 일을 하는지도 모를 뿐더러 SoundEvent 라는 이름만 정의 되어 있는 Class 이기 때문입니다. 그렇다면 어떻게 ? 이 클래스에 생명을 불어 넣을수 있을까요?   

dispatchEvent 를 사용 하면 됩니다.  

  1. /* dongkang . 2008-02-23
  2. SoundGauge Class  : checking sound 0 ~ 100 */
  3.  
  4. package interactive.sound{
  5.  
  6.  import flash.events.ActivityEvent;
  7.  import flash.events.StatusEvent;
  8.  import flash.events.Event;
  9.  import flash.events.TimerEvent;
  10.  
  11.  import flash.media.Microphone;
  12.  
  13.  import flash.display.Sprite;
  14.  import flash.display.MovieClip;
  15.  
  16.  import flash.utils.Timer;
  17.  
  18.  import customEvent.SoundEvent;
  19.  
  20.  public class SoundGauge extends Sprite {
  21.   private var device_arr:Array;
  22.   public var mic:Microphone;
  23.   private var gauge:MovieClip;
  24.   private var soundtimer:Timer;
  25.  
  26.   public function SoundGauge(_gauge:MovieClip):void {
  27.    gauge = _gauge;
  28.    device_arr = Microphone.names;
  29.    mic = Microphone.getMicrophone();
  30.    mic.gain = 40;
  31.    mic.rate = 11;
  32.    mic.setUseEchoSuppression(true);
  33.    mic.setLoopBack(true);
  34.    mic.setSilenceLevel(0,10);
  35.  
  36.  
  37.    for (var i:int =0; i < device_arr.length; i++) {
  38.     trace("   " + device_arr[i]);
  39.    }
  40.    
  41.    soundtimer = new Timer(1000);
  42.    soundtimer.start();
  43.    soundtimer.addEventListener("timer",onSoundhandler);
  44.   }
  45.  
  46.   private function onSoundhandler(e:TimerEvent) : void {
  47.    dispatchEvent(new SoundEvent(SoundEvent.CATCH));
  48.   }

 

 위의 클래스는 마이크에서 받은 소리를 1초 단위로 확인하기 위한 클래스 입니다. soundtimer 는 1초 단위로 onSoundhandler를 실행 시킬 것이고, 이 함수안에는 dispatchEvent 가 있어 SoundEvent.CATCH 가 호출되었다는 사실을 1초 단위로 계속 알려주게 됩니다. 그런데 누구 한테 알려 주는 걸까요? dispatchEvent 란 의미는 자기 자신이 해당되는 Class 에 SoundEvent.CATCH 를 걸어 주겠다는 의미 입니다. 다시 말해서 SoundGauge 에 SoundEvent.CATCH 이벤트가 걸리게 됩니다. 우리는 이 이벤트를 받아 오기 위해 SoundGauge 를 생성한 함수 내부에서 받아 올수 있습니다.  

 

var sg:SoundGauge = new SoundGauge();

sg.addEventListener(SoundEvent.CATCH, onCatch);

 

function onCatch(e:SoundEvent):void

{

 이함수는 어떻게 호출 되는 걸까요?

           SoundGauge 가 생성되자 마자 내부에 있는 soundtimer가 시작되기 때문에

         이 함수 또한 1초 마다 실행 되게 됩니다.

}

 

 

이처럼 dispatchEvent 는 정말 다양하게 중요하게 사용되는 메서드 입니다.
"이벤트를 이벤트 흐름으로 전달하고, 이벤트 대상은 dispatchEvent() 매서드가 호출된 EventDispatcher 객체 입니다. 쉬운 개념이 아닌 만큼 알게 되면 그동안 힘들게 했던 이벤트 전달을 손쉽게 적용할수 있으니, 그야 말로 최강 무기 라고 할수 있습니다. Actionscript 는 이벤트가 전부다 라고 말해도 될 만큼 이벤트중심으로 코드가 짜여 있습니다. 특히 이벤트를 전달하는 개념인 dispatchEvent 를 모르고 넘어 가신다면, 좋은 아이템을 버리고 싸우러 가는 것을 의미 할 정도로 중요합니다. 

 저도 알아 가고 있는 상태라 설명이 제대로 된지 모르겠습니다. 역시 잘못된 부분은 거침없이 태클 달아 주시고요, 잘 이해 안가는 부분은 알려 주시면 더 보충하도록 하겠습니다. 금요일 입니다. 주말 잘 보내시고 곧 있을 컨퍼런스가 기대가 되네요.