[Event] 메타데이타 태그는 이벤트와 이벤트객체의 타입을 mxml 속성으로 정의하고자 할 경우 사용하며,
보통 ActionScript클래스안에서 [Event] 메타데이타 태그를 정의할 때는 class 정의 전에 삽입하고,
mxml파일에 정의할 때는
<mx:Metadata>블록내에 정의한다.기본 문장 구조는 다음과 같다.
[Event(name="이벤트명", type="이벤트타입(패키지구조로 정의)")]
다음은 AS와 MXML에 정의할 때의 예이다.
-AS
public class ButtonLabel extends Button
{
...
}
-MXML
사용자 정의 클래스를 mxml태그로 구현하고 여기서 발생하는 이벤트를 mxml 이벤트 속성으로 사용하려면 [Event] 메타데이타<?xml version="1.0"?>
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Metadata>
[Event(name="myLabelChanged", type="flash.events.Event")]
</mx:Metadata> ....
</mx:Button>
태그를 정의해야 하지만 어플리케이션에서 mxml로 구현된 컴포넌트 자체를 레퍼런싱해서addEventListener로 이벤트 핸들러를 처리하거나 사용자 정의 클래스에서 이벤트를 발생시킬 때 이벤트를 Bubbling시켜서, 이 사용자 정의 클래스를 구현한 어플리케이션에서 addEventListener로 이벤트 핸들러를 처리하고자 한다면 [Event] 메타데이타 태그를 정의할 필요는 없다.
말이 약간 복잡한 듯 한데 예를 들자면 다음과 같다.
Button을 상속한 사용자 정의 클래스로 , Button의 label을 변경하고 변경되었음을 알리는 "labelChanged" 이벤트를 발생시키는 myLabel이라는 set메소드를 정의했다. 여기서 눈여겨 볼 것은 "labelChanged" 이벤트를 생성할 때, 버블링 옵션을 true로 해서 이벤트가 버블링되도록 했다는 것이다.
-1.1 ButtonLabel.as
package
{
import mx.controls.Button;
import flash.events.Event;
public class ButtonLabel extends Button
{
public function set myLabel(strLabel:String):void
{
// Button클래스의 set label 호출, labelChanged 이벤트 발생
this.label = strLabel;
// 이벤트 객체 생성, Bubbles를 true로 설정.
var eventObj:Event = new Event("labelChanged",true);
dispatchEvent(eventObj);
}
}
}이를 구현한 어플리케이션은 다음과 같다.
-1.2 MetaEventTest.mxml
-1.1 ButtonLabel.as의 12번째 라인 this.label = strLabel이 실행되면 Button클래스의 set Label 메소드가 실행이 되고 ButtonLabel 클래스내에서는 "labelChanged"이벤트가 발생한다.(기존 label값과 새로 지정한 값이 다를 경우에만 발생) 하지만 어플리케이션에선 이 이벤트를 리스닝할 수 없다. 왜냐하면 bubling이 되지 않기 때문에 클래스 레벨에서만 이벤트가 발생한다.
Button클래스를 열어보면 아래와 같이 바로 알 수가 있다.
-mx.controls.Button.as 소스 중...
[Bindable("labelChanged")]
[Inspectable(category="General", defaultValue="")]
/**
* Text to appear on the Button control.
*
* If the label is wider than the Button control,
* the label is truncated and terminated by an ellipsis (...).
* The full label displays as a tooltip
* when the user moves the mouse over the Button control.
* If you have also set a tooltip by using the tooltip
* property, the tooltip is displayed rather than the label text.
*
* @default ""
*/
public function get label():String
{
return _label;
}
/**
* @private
*/
public function set label(value:String):void
{
labelSet = true;
if (_label != value)
{
_label = value;
labelChanged = true;
invalidateSize();
invalidateDisplayList();
dispatchEvent(new Event("labelChanged"));
}
}
-1.2 MetaEventTest.mxml 어플리케이션 소스를 보면 tiButtonLabel 이라는 textInput의 change이벤트가
발생하면 dispatchLabelChange 메소드를 호출하고 24번째 라인 myButton.myLabel=tiButtonLabel.text; 에
의해 -1.1 ButtonLabel.as 15,16번째 라인의 labelChanged 이벤트가 발생된다.
이 이벤트는 버블링 되기 때문에 -1.2 MetaEventTest.mxml 어플리케이션 initApp 메소드에 정의한대로
onbtnLabelChange 이벤트 핸들러가 동작하게 된다.
복잡하게 설명했지만 한마디로 -1.1ButtonLabel.as의 set MyLabel 메소드 내에 12,16번째 라인에서 각각 이벤트가 발생되고(즉, 두 개의 이벤트 발생,둘 다 공히 "labelChanged" 이벤트) 어플리케이션에선 16번째 라인에서 발생된 labelChanged 이벤트만 리스닝하고 그에 따른 이벤트핸들러를 동작시킨다는 것이다.
여기서 -1.2 MetaEventTest.mxml 11번째 라인의 this.addEventListener를 myButton.addEventListener로 바꾸고, -1.1 ButtonLabel.as 15번째 라인의 new Event("labelChanged",true) 를 new Event("labelChanged") 로 바꿔보도록 하자. 어플리케이션의 이벤트리스너를 커스텀 컴포넌트인 myButton의 레퍼런싱을 통해서 리스닝하도록 바꾸고 myButton에서 발생시키는 labelChanged 이벤트의 버블링 옵션을 다시 false로 바꾼 것이다. 아래 swf 파일과 바로 위의 swf 파일의 차이점이 무엇인지 바로 알 수 있을 것이다.
자~ 달라진 점이 무엇인가?
this를 myButton으로 바꾸면서 이벤트를 버블링 할 필요가 없어졌고, -1.2 MetaEventTest.mxml 어플리케이션 initApp 메소드에 정의한대로 onbtnLabelChange 이벤트 핸들러가 2번 동작하게 된다.
왜 두번이냐고? 위에서 ButtonLabel.as 클래스, 즉 myButton에서 labelChanged 이벤트가 두번 발생(Button클래스내에서 발생하는- ButtonLabel.as 12번째 줄- labelChanged와 커스텀 클래스에서 발생하는-- ButtonLabel.as 16번째 줄- - labelChanged)하기 때문에 onbtnLabelChange 이벤트 핸들러도 2번 동작하게 되서 textArea에 두번씩 값이 찍히는 것이다.
이건 분명 의도하지 않는 결과다. 나 조차도 Button.as 클래스내에서 labelChanged라는 이벤트가 발생하는지 몰랐기 때문에 이런 일이 생긴 것이다. 단순히 "labelChanged"는 내가 만든 이벤트란 생각이었기 때문에
두번씩 찍히는 걸 보고 "왜 이러지" 의아해했다.
아무튼 내가 하고자 하는 말은 이게 아니기 때문에 각설하고...
위의 두 방식처럼..커스텀 클래스에서 발생하는 이벤트를 버블링해서 이벤트를 핸들링할 수도 있고, 커스텀 클래스 자체를 레퍼런싱하여 이벤트를 핸들링할 수도 있는데....[Event] 메타데이타 태그는 왜 쓰냔 말이다.. [Event] 메타데이타 태그 굳이 쓸 필요 없잖은가...적어도 내 생각엔...커스텀 클래스를 사용할 때, 내부에서 어떤 이벤트가 발생하는지 일일이 소스를 열어서 찾아 봐야한다면 많이 불편할 듯 하다.(누군가 API를 ASDoc으로 깔끔하게 제공해주고, 개발자가 이 API를 적극 활용한다면 필요 없을지도 모르겠다.)
개발된 커스텀 클래스에 대한 자세한 스펙따윈 알고 싶지 않고 코딩할 때 단순히 편하게 해주면 좋겠다.
코드를 구현하는 개발자 입장에선 mxml로 코드힌트가 되서 나오는게 정말 편하다. 그래서 개인적인 내 결론은...
글 도입부에 기술했듯이, "[Event] 메타데이타 태그는 이벤트와 이벤트객체의 타입을 mxml 속성으로 정의하고자 할 경우 사용한다" 이다..ㅋㅋㅋ 아님말구? (이건 뭥미..^^;)
자, 그럼 [Event] 메타데이타를 써보도록 하자.
-1.3 ButtonLabel.as
package
{
import mx.controls.Button;
import flash.events.Event;
//[Event(name="labelChanged", type="flash.events.Event")]
[Event(name="customLabelChanged", type="flash.events.Event")]
public class ButtonLabel extends Button
{
public function set myLabel(strLabel:String):void
{
// Button클래스의 set label 호출, labelChanged 이벤트 발생.
this.label = strLabel;
/*
이벤트 객체 생성.
아래 두줄을 주석처리하고 15번째 라인에서 이벤트가 발생하므로
[Event(name="labelChanged", type="flash.events.Event")]를 사용해도 됨.
그렇게 사용하면 코드 힌트로 labelChanged 이벤트 명이 보여진다.
*/
var eventObj:Event = new Event("customLabelChanged");
dispatchEvent(eventObj);
}
}
}
이제 customLabelChanged 이벤트를 코드힌트로 아래와 같이 사용할 수 있다. 위에 두 방식보다 훨씬 편하지 않은가? 아님말구 ㅋㅋ
이를 구현한 어플리케이션은 다음과 같다.
-1.4 MetaEventTest.mxml
-완성된 어플리케이션.
소스를 보다 보면 눈치 빠른 사람이라면.. -1.4 MetaEventTest.mxml의 30번째 라인의 textIput의 change 이벤트 속성도 mx.controls.TextInput 클래스에 [Event] 메타데이타 태그로 정의되어 있음을 알 수 있을 것이다.
검쉰님의 블로그에 [Flex] Event 메타태그 에 대해서 아주 깔끔하게 정리되어 있지만
주위에서 사용자 정의 클래스에서 발생시키는 커스텀 이벤트에 대해선 무조건 [Event] 메타데이타 태그를 정의하는 경우를 자주 보게 되서 다시 한번 정리해 보았다. 글 재주가 없어서 이해하기 힘들수도 있을테지만 다시 한번 읽어봐서 나쁠 건 없다고 생각한다.
말이 앞뒤가 안맞고 많이 어수선하지만 정리하면서 많이 배웠다.
다음은 [Inspectable] 메타데이타 태그에 대해서 정리할 예정이다. 예제 소스는 아래에...
MetaEventTest.zip


