Flex3.0&AS3 2008. 9. 29. 13:26

focus setting


<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/23/setting-focus-in-flex-using-the-focus-manager/ -->
<mx:Application name="FocusManager_setFocus_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

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

            private function submitButton_click(evt:MouseEvent):void {
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }

            private function resetButton_click(evt:MouseEvent):void {
                username.text = "";
                password.text = "";
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }
        ]]>
    </mx:Script>

    <mx:ApplicationControlBar dock="true">
        <mx:Button label="Set focus to Username"
                click="focusManager.setFocus(username);" />
        <mx:Button label="Set focus to Password"
                click="focusManager.setFocus(password);" />
    </mx:ApplicationControlBar>

    <mx:Form id="form"
            defaultButton="{submitButton}">
        <mx:FormItem label="Username:">
            <mx:TextInput id="username" />
        </mx:FormItem>
        <mx:FormItem label="Password:">
            <mx:TextInput id="password"
                    displayAsPassword="true" />
        </mx:FormItem>
        <mx:FormItem direction="horizontal"
                horizontalAlign="right"
                width="100%">
            <mx:Button id="submitButton"
                    label="Submit"
                    click="submitButton_click(event);" />
            <mx:Button id="resetButton"
                    label="Reset"
                    click="resetButton_click(event);" />
        </mx:FormItem>
    </mx:Form>

</mx:Application>
Flex3.0&AS3 2008. 9. 25. 10:45

sprite는 canvas에 addChild 안되는걸까?


왜 Sprite는 Canvas에 addChild 안되는 걸까요?

- Sprite는 무엇인가요?

먼저 Sprite는 무엇인지 잘 모르는 분들을 위해 설명을 곁들여보죠.
ActionScript 3 에서는 Sprite Class라 불리우는 새로운 Class를 사용하게 되는데... Sprite Object는 Movie Clip과 유사합니다만, Timeline이 없다는 것이 큰 차이점입니다. Sprite는 timeline을 요구하진 않는 곳에서 쓰일 수 있는 적합한 Base Class 입니다.


물론, Sprite를 FLEX에서 사용하고 싶다면 UIComponent에 addChild  하여서 사용하면 됩니다. (참고 : 지돌스타님 블로그)

하지만, UIComponent를 상속하고 있는 Canvas에는 왜 addChild가 되지 않는가 하는 것이 이 글의 주요 주제죠.


- Sprite을 Canvas에 addChild 하면 ?

여기서 분명한 것은 Sprite를 Canvas에 addChild하면
"TypeError: Error #1034: 유형 강제 변환에 실패했습니다. flash.display::Sprite@45cd351을(를) mx.core.IUIComponent(으)로 변환할 수 없습니다."
라고 컴파일시에 Error가 난다는 겁니다.

오류가 난 곳을 따라가보면 Canvas가 상속하고 있는 Container 클래스의 addingChild 메소드에서 나는 것을 알 수 있습니다.
 override mx_internal function addingChild(child:DisplayObject):void
 {
        // Throw an RTE if child is not an IUIComponent.
      var uiChild:IUIComponent = IUIComponent(child);  // 이 줄에서 오류가 납니다.
        ...
}


IUIComponent 타입인지 확인하고 있는데, Sprite는 IUIComponent type이 아니기때문에 오류가 나고 있는 것입니다.


- IUIComponent는 무엇인가요?

그럼 IUIComponent는 무엇일까요?
클래스 안에 있는 주석으로 다음과 같이 설명되고 있습니다.

 The IUIComponent interface defines the basic set of APIs that you must implement to create a child of a Flex container or list.

FLEX의 Visual Component의 기본은 UIComponent 입니다.
IUIComponent 인터페이스는 이 UIComponent 가 구현하고 있는 인터페이스로서 위의 설명에 따르면,
Flex의 Container 나 List의 child들은 IUIComponent 인터페이스를 구현하고 있어야 된다고 합니다.
(아니면 위 에러메세지 처럼 IUIComponent 타입이 아니라서 오류나죠 ㅡㅂㅡ)


- 그렇다면 Canvas는?

 Canvas Container UIComponent FlexSprite Sprite DisplayObjectContainer InteractiveObject DisplayObject EventDispatcher Object
인용 : Flexdocs.kr

위의 관계대로 만들어진 Canvas에는 IUIComponent가 구현된(다시 말해 UIComponent를 상속받는) 클래스들은
모두 addChild 될 수 있으나 그렇지 않은 클래스는 addChild 되지 못하게 됩니다.
Sprite는 IUIComponent 인터페이스를 구현하고 있지 않으므로
Container에는 addChild 할 수 없는 것입니다.




- Tip

Sprite를 Canvas 같은 Container 에 추가하여야 하는 일이 생긴다면 아래와 같이 클래스 만드셔서 addChild 하셔도 괜찮을 것 같네요. :)

package
{
    import flash.display.Sprite;
    import mx.core.UIComponent;

    public class mySprite extends UIComponent
    {
        private var sprite:Sprite;
 
        public function mySprite()
        {
             super();
   
             sprite = new Sprite();
         }
 
        override protected function createChildren():void
        {
            super.createChildren();
   
            this.addChild(sprite);
        }
        .....
    }
}

참고자료 :
[팁] Sprite 사용법
Flex 2 Beta 3 : Sprites



2007/11/20 - [Dev/Flex] - [FLEX] Coloring the Background of Cells

Flex3.0&AS3 2008. 9. 25. 09:23

컴파일된 플래시나 플렉스 SWF 파일에 접근하기


플렉스로 작업하다 보명 종종 컴파일된 파일에 접근해야하는 경우가 생깁니다. 플렉스로는 실제 플래시의 화려한 모션을

구현한다는것은 노가다에 가까운 일이므로.. 플렉스와 플래시로 연동만 잘하면 좋긴하지만 몇가지 문제점들이 있습니다.

 

컴파일된 SWF 를 플렉스에 가져오는 방법은 수없이 많습니다만 중요하다고 생각되는 몇가지만 적어보았습니다.

 

1. 외부 SWF 파일의 초기화 시점에대한 실수

 

외부 SWF 파일을 로드하기 위해서 기본적인 SWFLoader 컨텐츠가 있긴하지만 로드후에 바로 함수를 적용시킬때 종종

null 객체 참조오류에 부딛힌분들이 계실겁니다. 또는 애꿏은 플래시를 탓하던가 말이죠. 사실 SWFLoader 의

complete 이벤트만으로는 로드후에 초기화 함수를 호출하는데 문제가 있습니다. complete 이벤트는 다운로드를 모두 받았을때의

시점을 이야기하는것이기 때문이죠. 실제 로드후에 초기화 함수를 호출하려면 컨텐츠의 이벤트를 트리거 해야합니다.

 

 

 

<mx:SWFLoader id="FlashLoader" source="output.swf" complete="completeHandler()"/>

 

private function completeHandler():void

{

       MovieClip(FlashLoader.content).addEventListener(Event.ENTER_FRAME , initFlash);

}

 

private function initFlash(e:Event):void

{

       //플래시 초기화 실행

}

 

플렉스로 만들어진 SWF파일의 경우 MovieClip 이 아니기 때문에 조금 다릅니다.

 

 

<mx:SWFLoader id="FlexLoader" source="output.swf" complete="completeHandler()"/>

 

private function completeHandler():void

{

       FlexLoader.content.addEventListener(mx.events.FlexEvent.APPLICATION_COMPLETE , initFlex);

}

                   

private function initFlex(e:Event):void

{

       //플렉스 초기화 실행

}

 

 

2. 함수나 객체에 접근하기

 

플래시와 플렉스의 경우 구조 자체가 많이 다르기 때문에 접근하는 방법도 서로 다릅니다.

 

 

<mx:SWFLoader id="FlashLoader" source="flash.swf"/>

 

MovieClip(FlashLoader.content).함수();

MovieClip(FlashLoader.content).변수;

 

FlashLoader.content["root"].함수();

FlashLoader.content["root"].변수();

 

플래시는 root 플렉스는 application 으로 접근합니다.

 

 

<mx:SWFLoader id="FlexLoader" source="flex.swf"/>

 

FlexLoader.content["application"].함수();

FlexLoader.content["application"].변수();

 

함수나 변수에 접근할때 반드시 네임스페이스가 public 로 설정되어야 한다는 점도 잊지 마시기 바랍니다.

 

Flex3.0&AS3 2008. 9. 25. 09:21

HTTPService 에서 XML을 받아 DataGrid에 바인딩해보자


Flex를 어느 정도 하신 분들이라면 HTTPService 사용과 데이터 바인딩(binding)에 익숙해지셨겠지만, 제가 만난 분들 중에도

종종 실수를 하시는 분들이 계십니다. 그만큼 자주 사용하면서도 실수하기 쉬운부분입니다. 이번엔 HTTPService 에서 데이터를 읽어와

DataGrid까지 바인딩(binding)시키는 부분에서 실수하기 쉬운 부분에 대해 자세히 설명하려 합니다.

 

먼저 아래처럼 웹서비스(web service)를 선언해줍니다.

 

 

 

<mx:HTTPService id="service" resultFormat="e4x" result="resultHandler(event)" />

 

 

 

여기서 result="resultHandler(event)" 는 이벤트 내부적으로 event 라는 이벤트 인스턴스(instance)가 생성되는데 이것을

콜백함수(callback function)에 넣겠다는 뜻입니다. resultFormat 은 대부분 웹서비스는 XML 기반으로 데이터를 연동시킬 목적으로

구현할것이라면 e4x 라고 선언해주어야 나중에 뒷탈(?)이 없습니다. 그렇지 않으면 종종 원치않은 바이너리가 들어가는 경우가 생깁니다.

 

 

 

 

import mx.collections.XMLListCollection;

import mx.rpc.events.ResultEvent;

 

[Bindable] private var dataset:XMLListCollection = new XMLListCollection();

  

private function resultHandler(e:ResultEvent):void

{

    dataset = new XMLListCollection(new XMLList(e.result.node));

}

 

 

많은 분들이 이 부분에서 실수를 하는데 '예제로 배우는 Adobe 플렉스 2' 에 (저를 포함한 많은 분들이 이 책으로 시작하셨죠)

DataGrid 에 데이터를 바인딩 시키기는 부분이 나오는데 책에서는 HTTPService.lastResult 를 바로 DataGrid에 바인딩 시킵니다.

 

HTTPService.lastResult 을 바로 DataGrid에 바인딩 시켰을경우 데이터가 1개의 노드가 존재할때 문제가 null 객체에 접근 에러가

뜨고 말지요. XML이 한개 였을경우 데이터가 어레이(array) 형태가 아닌 오브젝트(object) 형태라고 인식하기 때문입니다. 때문에

번거롭지만 위 처럼 XMLList를 통해 어레이(array) 형태란것을 인식시키고 이것을 바인딩된 변수 dataset에 넣어주는것입니다.

 

저 함수에서 DataGrid.dataProvider 에 넣어줄수도 있지만 그렇게 했을경우 정상적인 바인딩이 이루어지지 않을뿐더러 버그를

유발할수도 있습니다. 외부로 들어온 데이터는 저렇게 모두 바인딩 변수에 넣어주시는 편이 좋습니다. 

 

바인딩을 설명하기위해 dataProvider 에 ArrayCollection 을 넣어서 설명하는 부분 때문에 ArrayCollection 에 담는 분도

계시더구요. 전에도 잠깐 언급했듯이 HTTPService 는 기본 XMLListCollection 을 사용하는것이 정석입니다.

XMLListCollection를 사용해야지만 또 나중에 필터링에 대해 깊이 들어갈때 도움이 됩니다.

 

 

 

<mx:DataGrid dataProvider="{dataset}" />

 

 

마무리는 다음과 같이 선언해주면 끝입니다. 간단하지만 의외로 실수하기 쉬운 부분이죠.

Flex3.0&AS3 2008. 9. 25. 09:07

ResourceModule 동적 리소스 모듈 만들기


이번에는 ResourceManager 를 이용하여 리소스들을 동적으로 로드 시키는 방법을 해보겠습니다.

ResourceManager 에는 동적으로 별도로 컴파일된 리소스들을 읽어오는 메소드 loadResourceModule 를 지원하고 있습니다.

 

StyleManager 가 CSS 을 컴파일하여 동적으로 읽어오는 방법이 있듯이 ResourceManager 또한 별도로 컴파일된

리소스 모듈이라 불리우는 컴파일된 파일을 읽어오는 방법을 지원하고 있습니다.

 

그럼 loadResourceModule 를 사용하여 컴파일된 리소스를 읽어오기에 앞서 ResourceModule 를 만드는 방법을 살펴 보겠습니다.

 

ResourceModule 의 기본이될 Application 을 하나 생성하고 ResourceBundle 을 지정합니다.

 

 

<?xml version="1.0" encoding="utf-8"?>

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

       <mx:Metadata>

             [ResourceBundle("resx1")]

             [ResourceBundle("resx2")]

             [ResourceBundle("resx3")]

       </mx:Metadata>

</mx:Application>

 

리소스 파일을 생성하는 방법과 ResourceBundle 사용법은 앞에서 설명드렸기에 넘어가겠습니다.

 

이렇게 간단하게 한개의 Application 안에 resourceBundle 를 설정하고 컴파일 하는것 만으로 ResourceModule 는 완성됩니다.

 

이제 컴파일된 ResourceModule 를 읽어오겠습니다.

 

 

resourceManager.loadResourceModule("resourceModule.swf" , true);

                          

resourceManager.getClass("resx1" , "IMG");