'Dev/Flex'에 해당되는 글 28건
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. 30. 16:10
플렉스 내에서 팝업(Popup)으로 창을 띄우려면 PopupManager 를 사용하게 됩니다. 이 때 팝업의 대상은 제한이 없습니다만(심지어 버튼이라도 팝업가능) TitleWindow 컴포넌트를 이용하는 편이 간편하게 처리가 가능합니다. 레퍼런스에서도 팝업관련 예제는 TitleWindow 컴포넌트를 이용하여 보여주고 있습니다. 이는 TitleWindow 컴포넌트가 레퍼런스에 소개된 것과 같이 팝업용으로 사용하기 위해서 Panel 컴포넌트를 확장하여 만들었기때문입니다. 간단하게 TitleWindow에 대한 활용예제는 여기를 참고하시기 바랍니다.

직접 팝업용 컴포넌트를 구현하여 사용하시는 분들도 있으시겠지만, 저 같은 경우는 TitleWindow 컴포넌트를 상속하여 팝업용 컴포넌트를 만들어 사용하고 있습니다. TitleWindow를 상속받으면 상단 좌측에 Close 버튼을 지원하고 Close버튼 클릭시에 CloseEvent가 발생하므로 보다 간편하게 사용할 수 있는 이점이 있습니다. 또한 상단 타이틀바를 클릭하여 드래그(Drag)해서 팝업 윈도우의 위치를 조정할 수 있기도 합니다.

내부 구현상 TitleWindow의 기능은 부모클래스인 Panel에서 거의 다 구현이 되어있고 Close 버튼을 보이게만 하는 정도입니다. 이러한 내용은 이전에 올린 포스트 :  2008/06/20 - [Dev/Flex] - [Flex] mx_internal 로 선언된 변수나 메소드에 접근하기 (namespace 의 사용) 에서 간단하게 언급하였으므로 참고하시면 되겠습니다.

위에서 TitleWindow를 이용하여 팝업시 이점으로 들었던 것 중에 타이틀바를 클릭하여 드래그(Drag)하면 팝업창의 위치를 조정할 수 있다고 한 것이 있었는데, 그렇다면 다른 컴포넌트의 경우에도 똑같이 드래그(Drag)시에 위치가 조정될까요? 대답부터 해보자면, Flex에서 지원하는 기본 컨테이너 컴포넌트 중에서는 TitleWindow와 Panel 만이 가능합니다. 왜냐하면 팝업창을 드래그(Drag)하여 위치 조정하는 기능은 Popupmanager 에서 부여된 것이 아니라, 해당 컴포넌트 자체에서 지원하는 것이 기 때문입니다. TitleWindow에는 팝업창으로 사용시에 드래그(Drag) 하여 위치를 조정할 수 있도록 기능이 구현되어 있으므로 가능한 것입니다.(Panel 같은 경우는 TitleWindow 의 모든 기능이 이미 구현되어 있으므로 팝업시에 드래그(Drag)도 가능합니다.)

여기서 한가지 의문점이 생깁니다. 팝업이 아니라 직접 addChild 하는 경우에 TitleWindow나 Panel은 드래그(Drag)가 되지 않습니다. 그럼 어째서 팝업시에는 드래그(Drag)가 가능한 것일까요? 위에서 분명히 PopupManager가 해당 컴포넌트들이 위치 조정 가능하도록 지원해주지는 않는다고 말씀드렸는데요, 사실 살짝 관여하기는 합니다. ;) 바로 팝업시에 팝업되는 컴포넌트의 isPopup 속성의 값을 true 로 변경해주는데, 이때문에 TitleWindow나 Panel 가 드래그(Drag) 하여 위치조정이 가능하게 된 것입니다.  아래의 코드가 Panel 에서 타이틀바를 클릭시에 호출되는 메소드인 titleBar_mouseDownHandler() 입니다. 코드를 보시면 isPopup 속성이 true 로 되어 있을시에 startDragging() 메소드를 호출하여 위치조정이 가능하게 되는 것을 아실 수 있습니다.



그렇다면 역으로 TitleWindow로 팝업을 띄웠을때 드래그(Drag)를 못하게 하려면 팝업 후에 isPopup 속성을 false로 바꾸면 되겠죠? 아래의 코드와 결과물은 isPopup 속성을 변경하여 팝업 윈도우가 움직이지 못하도록 하는 예제입니다. ;)

이번에는 반대로 isPopup 속성을 true로 변경하여 팝업이 아닌대도 바로 움직일 수 있게 해보도록 하겠습니다. MXML로 정의해 놓은  Panel 의 isPopup 속성을 true로만 변경하였습니다.


이상으로 간단하게 TitleWindow에 대해 다루어 봤습니다. 차후 포스팅에는  PopupManager에 대해서 한번 다뤄볼 생각입니다. ;)

참고문서 : 2009/05/20 - [Dev/Flex] - [Flex] 팝업매니저를 이용한 사용자 정의 컴포넌트의 제작


2008. 7. 10. 01:44
제가 Flex를 처음 접했을 때 이해가 안되던 부분은 Array와 ArrayCollection 에 대한 것이었습니다. Array를 이용해서 ArrayCollection을 만들긴 했었는데, 왜 그렇게 만들어야 하는지 조차 이해를 못했었죠. ;)

우선 Array 에 대해서 알아봐야겠습니다.
Flex 에 Array 는 자바의  Array와는 달리 동적이어서 크기를 지정하지 않고 임의대로 push, pop 메소드를 이용하여 아이템을 추가 및 삭제할 수 있습니다. 다만, 특정 인덱스 위치에 아이템을 추가한다 던가, 삭제한다던가 하는 것은 불가능 합니다. splice 메소드를 이용하여 특정 위치의 값에 대해 컨트롤 할 수 있습니다만, 상당히 번거롭습니다. 그리고 Array의 특정 아이템이 변경될 경우에 그 변경여부를 즉각 알 수가 없습니다. (var array:Array = new Array() 하는 것 보다 var array:Array = [] 이렇게 하시는 것을 추천합니다. 전자는 느립니다. 왜그런지는 자세히는 모르겠습니다. 에이레네님의 글을 보고 알았거든요 ㅎ)


이를 가능하도록 하여주는 것이 ArrayCollection 입니다.
다 시 말해서 ArrayCollection은 Array의 wrapper 클래스로 Array의 데이터를 핸들링해주는 역할을 합니다. 엄밀히 말해서는 ArrayCollection이 상속받은 ListCollectionView 클래스에서 지원해주죠. ArrayCollection은 단지 Array를 받을 source 라는 속성과 클래스 직렬화를 위한 readExternal, writeExternal 메소드(IExternalizable 인터페이스를 구현)만이 작성되어 있습니다.


그렇다면 ListCollectionView에 대해서 알아봐야겠습니다. 
ListCollectionView ICollectionView, IList, IMXMLObject 이렇게 3가지의 인터페이스를 구현하고 있습니다.(ListCollectionView 는 ArrayCollection과 XMLListCollection이 상속받고 있습니다. ArrayCollection은 Array에 대해서 컨트롤 하지만, XMLListCollection은 XML의 List 형태인 XMLList에 대해 컨트롤 합니다.) 여기서 중요하게 보아야 할 것은 처음 2개인 ICollectionView, IList 인터페이스입니다.

ICollectionView 인터페이스는 해당 Collection에서 데이터를 변경하지 않고, 데이터의 정렬 또는 필터링을 가능하게 해줍니다. 또한 해당 Collection에서 IViewCursor를 제공하여서 데이터에 대한 접근 및 변경을 지원합니다.


IList 인터페이스는 ICollectionView에서 IViewCursor를 이용한 순차적인 데이터접근과 달리 인덱스를 기반으로 하여 데이터에 대한 접근 및 변경을 지원합니다.


여기서 한가지 재미있는 것은 ListCollectionView는 내부적으로 IList 인터페이스를 이용하여 원본 데이터를 관리하고 있습니다. 위의 ArrayCollection에서 source에 Array를 반영해줄때 list 라는 변수에 넣어주는데 이 list 변수가 ListCollectionView에 보면
private var _list:IList;
와 같이 선언되어 있음을 알 수 있습니다.
ArrayCollecton 의 경우 Array, XMLListCollection의 경우 XMLList가 그 원본 데이터가 됩니다. 하지만 Array 와 XMLList 는 IList 인터페이스를 구현하고 있지 않습니다. 그렇기때문에 ArrayCollection에서는 IList를 구현하는 ArrayList, XMLListCollection에서는 XMLListAdapter 클 래스를 이용합니다. 이 2개의 클래스는 레퍼런스에서도 설명되어있지 않고, 빌더에서 Content Assist로도 나타나지 않습니다. 사용하기 원치 않았던 듯 합니다. ;) 하지만 ArrayCollection을 사용하기는 싫고 간편하게 데이터 접근이 필요한 경우에는 ArrayList를 사용해보는 것도 괜찮을 것 같습니다. (자바의 ArrayList 랑 똑같다고 생각이 듭니다.)


그럼 이상으로 간단하게 ArrayCollection에 대해 정리해보았습니다. 저도 이만 자야겠습니다. ;)
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. 7. 2. 18:11
회원가입 같은 페이지를 만들다보면 입력받을 값들이 상당히 많습니다.
이러한 값들이 실제 유효한 값인지 아닌지 판별하기가 좀 짜증나는 면이 있죠. 예전에 PHP로 회원가입 폼을 만들다보면 유효성 체크를 하기 위해서 JavaScript 로 각 필드의 값들을 체크하곤 했었습니다. (JavaScript 의 도움 없이 하려면 이 값들을 서버로 넘겨서(회원가입처리하는 php페이지) 서버에서 검증을 한 뒤에 하나라도 문제가 있으면 다시 그 화면을 표시해야되는 상당히 짜증나는 문제가 발생합니다. 그래서 클라이언트에서 해당 값들의 유효성을 체크하기 위해 JavaScript 를 이용했죠.)

물론 Flex에서도 비슷하게 해당 값(TextInput의 text 값)을 <mx:Script/> 안에서 체크하면 됩니다만, 코드를 매번 만들어야(복사해야)되니 짜증도 나고요.. ㅎ 상당히 귀찮은 면이 있었습니다. 그러나 다행이도 Flex 에서는 Validator 라는 것을 지원합니다.

유저가 유저 인터페이스에 입력하는 데이터는, 어플리케이션에 있어 적절한 내용의 경우도 있으나, 그렇지 않은 것도 있습니다. Flex 에서는, 오브젝트의 필드값이 특정의 조건에 적합하는 것을 감지하기 위해서 validator를 사용합니다. 예를 들어, 유저가 유효한 전화번호를 입력한 것을 확인하거나 string이 설정된 최소치 이상인 것이나, 우편 번호 필드에 올바른 자리수의 숫자가 포함되어 있는 것을 확인하거나 하기 위해서, validator 를 사용할 수 있습니다.

출처 : flexdocs.kr


이 Validator 는 아래와 같이 하위 Validator가 존재합니다. :
 
총 10개의 하위 Validator 가 존재하는데, Flex를 한국에서 만들지는 않아서 주민등록번호 Validator 는 존재하지 않습니다. ;) 없으면 어떻게 할까요? 그냥 체크안할 수도 없고 말이죠. 뭐 별수 있습니까? 그래서 만들었습니다!. 요즘은 회원가입시에 주민등록번호를 받지 않는 곳이 늘고 있습니다만, custom Validator를 어떻게 만들어야되는지 알아보기 위해, 흔히 만들어 보셨을 주민등록번호 Validator를 만들어 보았습니다. 주민등록번호의 유효성 체크 부분은 Flex Component 카페마요네즈라는 분이 올려주신 주민등록번호 체크 function이라는 글의 코드를 가져다가 썼습니다. (주민등록번호가 영어로는 RRN 이라더군요. RRNValidatort 라고 하면 어려울 것 같아 JuminBunhoValidator 이라고 이름지었습니다. (웃음) )

 

위의 주민등록번호 Validator를 이용하여 예제를 만들어보았습니다. 예제코드는  Flex  Reference에 Validator의 예제를 빌려왔습니다. ;)


한번 자신의 주민등록번호를 넣고 테스트해보세요. (저장되지 않으니 안심하시고... )

2008. 6. 21. 09:57
Flex에서 팝업용도로 많이 쓰는 TitleWindow이라는 클래스가 있습니다.
TitleWindow 의 구현코드를 보신 분은 아시겠지만 TitleWindow 에는 그렇게 많은 코드가 있지는 않습니다. (오히려 뭐가 이렇게 없어! 할 정도) 저도 상당히 의아했습니다. 주석을 빼면 정말 몇줄 안되는 코드였기 떄문이죠.

그 이유는 TitleWindow는 Panel을 상속해서 만들었는데 실제 TitleWindow에서 필요한 닫기버튼은 이미 Panel에서 구현되어 있고 단지 보이지만 않는 상태이기 때문입니다. TitleWindow에서는 showCloseButton 라는 get/set 메소드로 닫기 버튼의 보여지는 유무만 설정하면 됩니다.

그런데 여기서 좀 재미있는 부분이 있습니다. Panel에서 닫기 버튼이 구현되어 있다면 Panel을 상속받으면 그 닫기버튼도 사용할 수 있을까요? 그냥은 안됩니다. 왜냐하면 닫기버튼이 보이거나 안보이도록 설정하는 변수인 _showCloseButton이 mx_internal 로 선언되어 있기 때문입니다.



그럼 이걸 어떻게 사용하면 될까요? TitleWindow의 showCloseButton 라는 get/set 메소드 를 보면 해답을 찾을 수 있습니다.



showCloseButton 속성의 코드가 좀 특이하죠?
TitleWindow 의 코드 상단에
use namespace mx_internal;
이라고 작성되어 있습니다. mx_internal 이라는 namespace를 사용하겠다는 것이지요. 이렇게 설정되면 showColoseButton 속성과 같이 mx_internal로 선언된 _showCloseButtion 변수에 접근하시면 됩니다.
return mx_internal::_showCloseButton;      //이렇게 해도 되고 또는,
return _showCloseButton;                       //이렇게만 해도 되긴 합니다
그렇다면 TitleWindow 는 Panel을 상속받았으니 그렇다 치고, 외부에서 Panel 객체의 _showCloseButton 변수를 바로 접근할 수는 없을까요? 안된다고요? 그럼 안되는데요! 안되면 제가 이 글을 쓸 이유가 없어집니다. ;) 바로 아래와 같이 가능합니다.


그래도 화면에 보이는 예제가 하나 필요하겠죠? 이번에는 TextArea로 예제를 하나 만들어보겠습니다.
(loveDev 블로그에서 아이디어 얻었습니다)
Flex에서 한글을 입력시에는 버벅이는 문제(천천히 타이핑 되는 문제)가 있었습니다. 이 문제를 해결하기 위해서 frame rate 를 올린다던가 하는 방법을 사용했었는데, Adobe Flex 공식사이트에 블로그에 올라온 글에서 어이없게도(?) TextField 의 alwaysShowSelection 속성을 true로 바꾸어주면 해결된다는 것이었습니다. 왜 그런지는 저도 정확하게는 잘 모르겠고... ^^;

아 무튼 Flex에서 한글 입력을 받는 TextInput, TextArea 등도 내부적으로 TextField를 상속한 UITextField 를 사용하고 있습니다. 그렇다면 이 UITextField 를 받아와야겠습니다만, 이게 또 골치아픕니다. TextArea나 TextInput 은 이 UITextField가 protected로 선언되어 있기때문에 외부에서 접근하는 것이 불가능합니다. 그래서 상속을 받아서 접근하던지, 아니면 여기와 같이 해결을 해야됩니다.

그러나 다행이도 이 TextField를 반환해주는 getTextField()라는 메소드가 존재합니다.


그렇다면 UITextField에 직접 접근하여 텍스트를 입력하려면 getTextField() 메소드를 사용하여야 할텐데요, 위의 코드에서 보셨다시피 mx_internal 로 선언되어있습니다. 이럴때는 위에서 설명드린데로 하면 되겠죠?

이 getTextField를 이용하여 TextArea에 한글입력을 개선한 예제입니다.
아래에 있는 TextArea에만 alwaysShowSelection의 값을  true로 설정을 해주었습니다. 위 아래 TextArea에 한글을 입력해보세요. ;)



유용한 정보 되셨길 바랍니다. ;) (오창훈님 감사합니다. ㅎ)


--- 파폭3에서 예제에 한글 입력이 안되네요.. ㅡㅡ; 왜 이러지;; 티스토리에 swf 업로드 하면 object 태그는 생성되는데 embed 태그가 없네요. 이래서 한글 입력이 안되었군요. ㅡㅡ; wmode 속성이 window 일때는 한글 입력이 됩니다. opaque나 transparent 속성은 한글 입력이 안됨..;
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. 5. 28. 15:35
제목이 좀 뜬금없다... 라고 생각하시는 분이 있으실 것 같습니다. ;)

'XML 그냥 toString() 하던지 toXMLString() 하면 String 만들어주잖아?' 라고 말이죠.
물론 XML의 toXMLString() 메소드를 호출하면 String 으로 만들어줍니다. 다만, 이게 개행문자(\n)가 포함되어있어서 문제가 됩니다. (개행문자 같은 metasequences는 이 곳을 참고하세요.)



위와 같은 코드가 있다고 할 때에 sourceXML.toXMLString() 해서 나온 String을 담고 있는 xmlString 에는 무엇이 들어있을까요?
XML을 String으로 만들었으니 아래와 같이 있겠죠?
 <root><items><item classtype="UIComponent" id="myUIComponent" x="10" y="10" width="20" height="20"/><item classtype="Canvas" id="myCanvas" x="20" y="40" width="30" height="30"/><item classtype="Panel" id="myPanel" x="30" y="60" width="40" height="40"/></items></root>

실제로 위와 같이 들어있을까요? 아닙니다.
 실제 아래와 같이 개행문자가 포함된 아래의 String이 들어있습니다.

 <root>\n  <items>\n    <item classtype="UIComponent" id="myUIComponent" x="10" y="10" width="20" height="20"/>\n    <item classtype="Canvas" id="myCanvas" x="20" y="40" width="30" height="30"/>\n    <item classtype="Panel" id="myPanel" x="30" y="60" width="40" height="40"/>\n </items>\n</root>

XML을 toXMLString()으로 String으로 만들면 계층구조에 맞게 개행문자를 넣어서 String을 만들어줍니다. 그래서 해당 String을
trace() 를 해보면 아래와 같이 콘솔에 XML의 계층구조로 보이게 됩니다.
( toString() 을 사용해도 마찬가지 입니다.)

사용자 삽입 이미지


Flex에서 위의 xmlString 을 다시 XML 로 만들더라도 아무런 문제는 없습니다.
(targetXML 에 sourceXML과 같은 XML 이 아무런 문제없이 담깁니다.) 하지만, 이렇게 변환된 String을 서버에서 사용시 문제가 생깁니다. 저는 HTTPService에서 자바 서블릿(Servlet)을 호출하여 위와 같은 XML 데이터(파라미터 이름:mydata)를 보내어서 일련의 작업을 하려고 했습니다.  아래는 해당 값을 받는 서블릿입니다.



request.getParameter("mydata");  라고 구현하여서 실제 Flex 에서 보낸 XML 데이터를 String에 담았습니다. 그러나 이때 이 정보를 DOM 파서를 이용하여 실제 XML로 처리하고 싶어 Document 객체를 만들어 쓰는 과정에서 문제가 생깁니다. 각 노드들의 정보를 가지고 올때 이상한 문자 들어있지 않나...;; Flex에서는 XML을 보냈으나 실제 서블릿에서 받는 데이터는 개행문자가 담겨있는 위와 같은 String 이기 때문입니다.

이러한 문제때문에 Flex에서 XML 을 String으로 만들때 개행문자를 없애는 것에 대해 고민을 했습니다.
답이 안나오더군요. -_-; 어떻게 해야되는지도 모르겠고요. 해서 toXMLString() 대신에 사용할 정적 메소드를 하나 만들었습니다.

소스 수정 - 2008. 5. 29.

(남남남 님께서 덧글로 남겨주신 g 플래그를 사용함)

수정 전 소스 열기



위의 Utils.toXMLString()을 이용하여 다시 XML을 String으로 변환해보면 (var xmlString:String = Utils.toXMLString(sourceXML);) 맨 처음 예를 들었던 것과 같이 개행문자와 빈칸이 없는 String을 보실 수 있습니다. (노드사이에 빈칸이 있으면 그 것도 문제가 되더라구요)

코드가 좀 추합니다. ^^; 서버에서 제가 잘못처리해서 문제가 되었을지도 모르겠습니다.
더 좋은 방법을 아시는 분께서는 피드백 주시면 정말 감사하겠습니다. :)

2008. 6. 3. 추가

이정웅님께서 XML을 toString() 이나 toXMLString() 하면 개행문자가 포함되는 것에 대한 이유를 알려주셨습니다.
다름아닌 XML 클래스의 prettyPrinting 속성이 있었네요. 기본값이 true 인데, false 로 바꾸면 한줄로 주르륵 나옵니다. ㅜㅜ
(이쁘게 프린팅한다라... ㅜㅜ)
2008. 5. 13. 20:35
Canvas에 cornerRadius="20" 을 주어서 테두리를 라운드하게 변환한다고 하더라도, 자식 객체인 Button이 라운드 처리된 영역을 빠져나가면 아래와 같이 Button이 라운드 처리된 영역을 빠져나와있는 것을 보실 수 있습니다.




라운드로 처리하더라도 벗어나는 자식객체가 문제가 됩니다.
그렇다면, 만약에 컴포넌트가 원형이어야 된다면 어떨까요? 라운드 처리된 곳도 빠져나가는데, 원형의 컴포넌트가 필요하다면?
원형을 벗어나는 영역은 화면에서 나타나지 않게 하면 간단하게 해결 할 수 있습니다. 이럴 때 mask를 쓰면 됩니다.

maskDisplayObject 의 속성으로 mask로 할당된 DisplayObject 의 영역만큼만 해당 컴포넌트를 보여주게 됩니다.
나머지는 화면에 나타나지 않게 되죠. 아래는 레퍼런스에 있는 마스크 예제입니다.
 
 
▲ 네모난 mask를 Drag 해보세요. mask 영역만큼만 TextField가 보입니다.


그럼 위에서 보신 mask를 이용하여 Canvas를 상속받은 myCircleCanvas라는 이름의 둥근 컴포넌트를 만들도록 하겠습니다.
위의 소스에서는 mask를 Sprite 객체를 이용하였습니다만, Flex에서는 Canvas에 Sprite 객체를 addChild 하면 오류가 나므로(Canvas가 상속하고 있는 Container에 addChild 시 IUIComponent가 구현되어있어야 하므로), UIComponent를 이용하도록 하겠습니다.

( 참고: 왜 Sprite는 Canvas에 addChild 안되는 걸까요? )

 UIComponent Inheritance FlexSprite Inheritance Sprite Inheritance DisplayObjectContainer Inheritance InteractiveObject Inheritance DisplayObject

레퍼런스에서 마스크로 사용하였던 Sprite 나 현재 mask로 사용하는 UIComponent는
둘 다 DisplayObject를 상속하고 있으므로 mask 로 할당하여도 됩니다.


아래는 myCircleCanvas 클래스의 코드입니다.
컴포넌트의 구분을 위해 결과물에는 backgroundColor 값을 주었습니다.


 

결과물은 myCircleCanvas 객체에 Button을 올려놓은 모습입니다.
둥근 mask 영역 밖으로 벗어나는 Button의 영역은 화면에서 나타나지 않음을 확인하실 수 있습니다.
이상 mask를 이용하여 둥근 컴포넌트를 생성하는 것에 대해 간단하게 다루어 보았습니다.
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. 쓰다보니 또 길어졌네요.. 별 내용 아닌데.. ㅜㅜ
prev"" #1 #2 #3 next