'Event'에 해당되는 글 5건
2008. 8. 7. 14:21
Flex에는 크게 MXML과 ActionScript 로 구현되고 있는데, 내부적으로 MXML이 ActionScript 로 변환되어 SWF로 빌드 됩니다. MXML이 ActionScript 로 변환되는 것을 볼 수도 있는데요, keep-generated-actionscript 속성을 바꿔주면 됩니다. 속성 지정 방법은 시난님의 블로그에서 잘 정리해놓으셨습니다. (SliverLight의 경우는 Flex와 다르게 CS 코드가 XAML을 변환시키는 구조라고 하더군요)

실제로 간단하게 속성을 지정하여 변환을 하여 보면 참 새로운(이해 잘 안되는) 코드들이 마구 쏟아져나옵니다. 특정 MXML Application을 생성하면 관련된 파일 4개가 생성이 됩니다. (다른 것들은 보통 특정 스타일 지정 ActionScript 클래스이거나 속성 관련)

예를 들어 test.mxml 파일이 있다면 아래와 같이 생성이 되게 됩니다.
  • test-generated.as
  • test-interface.as
  • _test_FlexInit-generated.as
  • _test_mx_managers_System.as
본 포스트에서 살펴볼 것은 처음에 있는 xxx-generated.as 입니다. 이해를 쉽게 돕기 위해서 간단하게 MXML Application을 만들어보겠습니다. MXML.mxml 이라고 이름 붙혀보았습니다. (조악한 네이밍. ㅜㅜ)


위와 같이 MXML이 생성이 되었다면 아래와 같이 MXML-generated.as 가 생성이 됩니다.
(설명할 부분만 수록하도록 하겠습니다. - 길이가 길어서...)



MXML Application 이기 때문에 클래스는 Application 을 상속받고 있습니다. 그 바로 밑에 보면 흔히 쓰이지 않는 UIComponentDescriptor 타입의 변수가 보입니다.

UIComponentDescriptor 인스턴스는, 비주얼 컴퍼넌트의 인스턴스의 MXML 태그로 지정된 정보를 캡슐화합니다.

MXML 파일내의 대부분의 태그는, UIComponent object의 트리를 설명하는 것입니다. 예를 들어,<mx:Application> 태그는 UIComponent object를 나타내, 그 child containers와 컨트롤도 모두 UIComponent object입니다.

MXML 컴파일러는, 각각의 MXML 태그를 UIComponentDescriptor 인스턴스에 컴파일 합니다. 엄밀하게는, MXML 컴파일러는 ActionScript 데이터 구조를 자동 생성합니다. 이것은, UIComponentDescriptor object의 트리가 됩니다.

실행시에, Container 클래스의 createComponentsFromDescriptors() Methods는, 컨테이너의 childDescriptors 배열의 UIComponentDescriptor object내의 정보를 사용해, 컨테이너의 아이인 실제의 UIComponent object, 및 한층 더 깊은 자손을 작성합니다. 컨테이너의 property creationPolicy 의 값에 따라서는, 어플리케이션의 기동시에 컴퍼넌트의 일부가 표시될 때, 또는 어플리케이션의 개발자가 수동으로 createComponentsFromDescriptors() Methods를 호출했을 때에, 자손이 작성되는 일이 있습니다.

통상, UIComponentDescriptor 인스턴스를 스스로 작성할 것은 없습니다. Container 클래스의 childDescriptors 배열을 경유해, MXML 컴파일러가 자동 생성한 인스턴스에 액세스 할 수 있습니다.

출처 : flexdocs.kr


설 명이 좀 어려운데요, 다시 말해서 MXML로 정의된 정보를 모두 가지고 있게 된다는 것입니다. 내부적으로 트리형태로 자식 컴포넌트들도 다 가지고 있게 되는데, 실제로 UIComponentDescriptor 타입의 _documentDescriptor_ 변수가 Application 이고, 그 자식으로 추가된 Button 컴포넌트는 childDescriptors로 추가되어 있습니다. 물론 Button 컴포넌트도 UIComponentDescriptor 타입이 되죠. 만약 버튼에 자식 컴포넌트가 존재했다면 childDescriptors 에 정의되어 있을겁니다.

여기서 잠시 Application에 childDescriptors로 정의된 Button 을 다시 한번 보겠습니다.

여기서 잠시 보실 것은 Button에 설정해놓은 click 이벤트입니다. 클릭시에 "___MXML_Button1_click" 를 호출하도록 되어 있는데요, 해당 메소드로 가보면 제가 정의한 clickEventHandler 를 호출하도록 하고 있습니다.


특정 이벤트에 대해서 이벤트 핸들러(event handler)를 설정하게 되면 1. 해당 이벤트에 대해서 호출된 메소드를 생성하고 2. 그 메소드가 이벤트 핸들러를 호출하게 하는 방식입니다.

저는 이 구조를 처음 봤을 때 전부터 궁금했던 의문점이 하나 풀렸습니다.

위와 같은 코드가 있다고 할때에 이 것을 ActionScript 로는 어떻게 할까 하는 것이었습니다. ActionScript 로는 addEventListener 메소드를 이용해야 되는데, 핸들러 메소드에게 따로 파라미터를 던질 방법이 없었던 거죠. 커뮤니티에도 이와 같은 질문들이 가끔씩 올라왔기도 했고, 저도 상당히 궁금했었습니다.

살짝 감이 잡히시나요?

각 버튼의 이벤트 핸들러가 생성되고 그 이벤트 핸들러에서 위에서 지정한 clickEventHandler를 호출하게 됩니다. 참 난감하더군요 ;)

아무튼 뭐 살짝 MXML이 ActionScript 로 변환되는 과정에 대해 살짝 알아보았습니다. ;)
PopupManager 관련 글은 아직 준비중입니다.. ㅜㅜ



2008-08-20 본문 복구 완료
2008. 7. 8. 15:27
사용자 정의 컴포넌트(custom component)를 만들었을때, 특정 이벤트를 발생시켜야하는 경우가 종종 있습니다. 마치 Button 을 사용자가 Click 하였을 때, Click Event가 발생하는 것 처럼 말이죠.  아래의 예제는 TextInput을 상속한 MyTextInput이라는 사용자 정의 컴포넌트입니다. 이 컴포넌트의 추가적인 기능으로는 키 입력시 'backspace' 를 입력하면, backspace 이벤트를 발생시키는 것입니다. (MXML로 만든 코드만 올려놓았는데, AS로 만든 버전도 같이 올렸습니다. 둘다 할 줄 알아야 좋죠 ㅋ)

MXML 로 만든 MyTextInput 컴포넌트 (MyTextInput.mxml)

AS로 만든 MyTextInput 컴포넌트 (MyTextInput.as)


keyDown 이벤트가 발생할때에 입력한 값이 backspace에 해당하는 '8' 이면  backspace 이벤트를 발생하도록 하였습니다. 여기서 눈여겨 보셔야 할 것은 Event 메타태그인데요. 위의 코드에서 아래와 같이 선언하였습니다.
<mx:Metadata>
  [Event(name="backspace",type="flash.events.Event")]
</mx:Metadata>
'선언해 놓은 컴포넌트에서 발생되는 이벤트가 이런 것이 있다~' 라고 선언해준다고 생각하시면 되겠습니다. 2가지를 적어야 하는데요, name과 type 입니다. name에는 해당 이벤트 이름, type 에는 해당 이벤트 클래스를 적어주시면 됩니다. 위와 같이 선언해놓으면 아래와 같이 name이 MXML 상에서 아래의 이미지와 같이 이벤트로 표시됩니다.



이 backspace 이벤트를 이용하여 아래와 같이 예제를 한번 만들어보았습니다. 사용자가 backspace 키를 누르면 아래의 TextArea 에 backspace를 눌렀다는 메세지가 나오게 됩니다.







그 렇다면 상단의 코드에서 보시면 MyTextInput 컴포넌트에서  keyDown 이벤트 핸들러를 지정한 2행을 보시면 TextInput 에도 keyDown 이벤트에 대해서 메타태그가 선언되어 있다 라고 유추해볼 수 있습니다. 실제로 TextInput 에는 레퍼런스에서 볼 수 있듯이 TextInput에서 정의된 4개의 이벤트가 아래와 같이 메타태그로 선언되어 있습니다.



keyDown 이벤트는 InteractiveObject 에서 정의되어 있어서 소스를 직접 확인할 수는 없네요. 안타깝습니다. ;)

이와 같은 자료는 지용호님의 블로그에 [Flex 2.0.1]커스텀 컴포넌트에 사용하는 Metadata 태그 소개 라는 포스트가 존재합니다만, 아직 어려워하시는 분들이 있는 것 같아 다시한번 설명해보았습니다.

이상으로 Event 메타태그에 대해서 알아보았습니다. ;)
2008. 6. 3. 12:58
만약 캔버스(Canvas)에 더블클릭(doubleClick)을 하면 어떠한 동작을 하는 코드를 만들 필요가 있다고 할 때, 당연하게 아래와 같이
라던지,

이렇게만 처리하면 doubleClickEventHandler() 에서 이벤트를 받을 수 있을 것이라 생각됩니다만,
더블클릭(doubleClick)을 사용하려면 한가지 더 설정 해주어야 할 것이 있습니다.

바로 doubleClickEnabled 라는 속성입니다.
(이 속성은 최초 InteractiveObject 에서 정의된 속성입니다.)
아 래의 코드는 Canvas에서 사용하는 Container 에서 재정의한 doubleClickEnabled 속성입니다. Container 에서 doubleClickEnabled 속성을 설정하게 되면 자식객체들도 doubleClickEnabled 속성을 동일하게 적용하도록 구현되어 있습니다.(고로 부모만 설정하면 자식들도 죄다 동일하게 설정됩니다.)
물론 UIComponent 에서도 동일한 기능을 하도록 재정의되어 있습니다.



여기서 의아해 하시는 분도 있을 것 같습니다. '난 그냥 하니까 잘 되던데?' 라고 말이죠.
Flex 2에서는 기본값이 true 였기 때문에 위의 2가지 방법으로 바로 더블클릭(doubleClick)을 사용할 수 있었습니다만,
Flex 3에서는 기본값으로 false 가 설정되어 있기때문에 더블클릭(doubleClick) 이벤트를 받으려면 true로 설정 해주셔야 됩니다.

아래는 캔버스(Canvas)에 더블클릭(doubleClick)을 하면 팝업창이 뜨는 코드입니다.
왼쪽에 캔버스는 doubleClickEnabled 속성이 true로, 오른쪽은 false 로 설정되어 있습니다.


아래는 실제 결과물입니다. ;)

2008. 4. 22. 14:21
Flex 의 DataGrid 는 상당히 유용한 컴포넌트입니다. 표 형태의 데이터를 출력하기 참 좋거든요.
이때 출력된 데이터중에 어떤 한 데이터를 출력하여 그 데이터에 대해서 작업을 해야할 때가 있습니다.
예를 들어 게시판의 글을 클릭하여 그 글을 보고자 하는 App를 작성한다고 합시다.

이때 보통 아래의 소스와 같이 DataGrid의 click 이벤트를 이용합니다.



click="clickEventHandler(event)" 라고 정의하여 해당 DataGrid 가 클릭되었을때 clickEventHandler() 메소드를 호출하게 됩니다.
이 해당 메소드는 다음과 같이 정의하였습니다.


하지만 위의 처리방식에는 문제가 있습니다.
clickEventHandler() 메소드에서 DataGrid의 selectedItem 속성을 이용하여 선택된 아이템에 접근하게 되는데, 만약 아무런 값이 없는 곳을 클릭한다면 어떻게 될까요? 이 때도 click 이벤트는 발생하게 되어 clickEventHandler() 메소드가 호출되겠지만, 선택된 아이템이 없으니 selectedItem 은 null 이 되게 됩니다. 그렇기에 위의 소스 6번째 줄의 selectedItem.url에서 에러가 발생하게 됩니다.
(헤더를 클릭해도 에러가 납니다. -- 추가)

물론 try catch 문을 이용하여 에러처리를 하면 됩니다만, 발생할 것이 예상되는 에러를 예외처리한다는 것은 그리 권장할 만한 방법이 아닙니다.

에러가 발생하지 않으면 Alert 창이 떠야하지만, 에러가 발생해서 Alert 창이 뜨지 않습니다. debug 용 flash player 를 설치하신 분은 다음의 에러메세지를 보실 수 있습니다.
TypeError: Error #1009: null 객체 참조의 속성이나 메서드에 액세스할 수 없습니다.
 at ClickTest/clickEventHandler()
 at ClickTest/__myDG_click()
 

이런 경우 실제 필요한건 아이템을 선택하는 것이지 DataGrid를 선택하는 것이 아닙니다.
이럴때 사용하기 좋은 이벤트가 바로 itemClick 이벤트 입니다.

itemClick event 
유저가 컨트롤내의 아이템을 클릭했을 때에 dispatch됩니다.
ListEvent.ITEM_CLICK 정수는,itemClick 이벤트에 관한 ListEvent object의 type property의 값을 정의합니다. 이 이벤트는, 컨트롤내의 가시 아이템 위에서 유저가 마우스를 클릭한 것을 나타냅니다.
출처 : flexdocs.kr

click 이벤트 대신 itemClick 이벤트를 이용하여 동일한 어플을 만든다면 위와 같은 문제는 해결되게 됩니다.
(Flex 3는 아닙니다만, Flex 2 에서는 DataGrid의 Header를 클릭해도 itemClick 이벤트가 발생됩니다. 완전히 해결은 안되는군요. 의견주신 유영상님 감사드립니다. - 추가) 
아래는 최종 샘플코드입니다.





더블클릭시 사용할 수 있는 itemDoubleClick 이벤트도 있으니 참고하시길 바랍니다.

ps. 쓰다보니 또 길어졌네요.. 별 내용 아닌데.. ㅜㅜ
2008. 3. 17. 17:08

Flex 에서 MXML로 정의한 버튼이 다음과 같이 있다고 가정합니다.

 <mx:Button id="btnAlert"  label="Alert!" />


이 버튼을 클릭할 때 어떠한 동작을 하고자 하면 해당 버튼에 다음과 같이 클릭 이벤트 핸들러를 등록시켜주면 됩니다.

Script ---

public function alert(evt:MouseEvent):void
{
  Alert.show("Hello, Flex!", "Alert");
}

MXML ---

 <mx:Button id="btnAlert" label="Alert!" click="alert(event)" />


만약, 실제 버튼을 클릭하지 않고서 버튼을 클릭한 것과 같은 이벤트를 수동으로 발생시키려면 어떻게 해야할까요?
이럴때 필요한 것이 dispatchEvent 입니다.

dispatchEvent 의 구조는 다음과 같습니다.
objectInstance. dispatchEvent(event:Event)

자세한 설명은 수동에 의한 이벤트의 송출(Dispatch)  에서 참고하도록 하고 본 포스트에서는 생략하겠습니다.


아래에 보여드릴 소스는 캔버스를 MXML로 정의하여 이 캔버스를 클릭하였을때 버튼을 클릭한 것 과 같이 수동으로 이벤트를 발생시킴으로써 버튼을 클릭하였을 때와 같이 팝업이 뜨도록 하고 있습니다.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">

    <mx:Script>
        <![CDATA[
   
        import mx.controls.Alert;

        public function alert(evt:MouseEvent):void
        {
            Alert.show("Hello, Flex!", "Alert");
        }

        public function canvasClick(evt:MouseEvent):void
        {
            btnAlert.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        }

        ]]>
    </mx:Script>

    <mx:Canvas x="44" y="79" width="200" height="153" backgroundColor="#FF0000" borderStyle="solid"
            cornerRadius="20" click="canvasClick(event)">
        <mx:Label text="Click Here!" horizontalCenter="0" verticalCenter="0"/>
    </mx:Canvas>

    <mx:Button id="btnAlert" x="271" y="137" label="Alert!" click="alert(event)"/>

</mx:Application>

dispatchEvent 를 이용하여 마치 버튼을 클릭한 것 처럼 MouseEvent.CLICK 이벤트를 버튼에 dispatch 함으로써 버튼에서 클릭 이벤트 핸들러로 등록해놓은 alert() 메소드가 실행되게 됩니다.

물론 위의 예제에서는 단순히 클릭시에 Alert 을 띄우는 작업으로 그쳤기에 문제가 없었지만, 실제 클릭이벤트와 관련된 작업이 필요할 경우 새로 생성해준 마우스이벤트 (new MouseEvent(MouseEvent.CLICK)) 상세한 값들을 제어할 필요가 있습니다.

MouseEvent (type:String , bubbles:Boolean = true, cancelable:Boolean = false, localX:Number , localY:Number , relatedObject:InteractiveObject = null, ctrlKey:Boolean = false, altKey:Boolean = false, shiftKey:Boolean = false, buttonDown:Boolean = false, delta:int = 0)

와.. 많다.;;;

prev"" #1 next