캠핑과 개발


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="doInit();">
<mx:Script>
<!![CDATA[import mx.collections.ArrayCollection; // this holds the grid data
[Bindable]
private var myData:ArrayCollection = new ArrayCollection();private function doInit():void{
myData.addItem({fname:"Joe",lname:"Bloggs"});
myData.addItem({fname:"Joe1",lname:"Bloggs"});
}

private function buildToolTip(item:Object):String{
var myString:String = "";
if(item != null)
{
myString = myString + "Firstname : " + item.fname + "\n";
myString = myString + "Lastname : " + item.lname + "\n"
}
return myString;
}
]]>
</mx:Script>
<mx:DataGrid id="dGrid"  dataProvider="{myData}"  visible="true" dataTipFunction="buildToolTip">
<mx:columns>
<mx:DataGridColumn dataField="fname" headerText="FirstName" showDataTips="true" />
<mx:DataGridColumn dataField="lname" headerText="LastName" showDataTips="true" />
</mx:columns>
</mx:DataGrid>
</mx:Application>


flex에서 bitmap 관련 프로젝트를 진행하다가 결과물을 인쇄 또는 이미지로 저장을 하는 부분이 있어서 추후에도 이를 잊어버리지 않도록 간단한 예제와 함께 메모를 한다. 내용 샘플은 어떤 의미없는 비트맵 객체를 생성후 인쇄버튼과, 이미지 저장버튼을 누르게 되면 출력, 또는 이미지 파일로 저장이 된다. 여기에서 이미지 저장은 로컬 PC로 저장이 된다.
또 주석처리한 부분은 서버로 이미지를 저장할 경우 서버에서 이를 처리하기 위한 내용이다. 서버에서 이를 처리하기 위해서는 Server에서의 파일이 필요한데 이 부분은 첨부한 소스를 보면 된다.


예제화면

예제화면



source))

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
 creationComplete="init();"
 >
 <mx:Script>
  <![CDATA[
   import org.gif.encoder.GIFEncoder;
   import com.saeasoft.util.UploadPostHelper;
   import mx.collections.ArrayCollection;
   import mx.graphics.codec.PNGEncoder;
   import mx.graphics.codec.JPEGEncoder;
   import mx.graphics.codec.IImageEncoder;
   
   import mx.printing.FlexPrintJobScaleType;
   import mx.printing.PrintAdvancedDataGrid;
   import mx.printing.FlexPrintJob;
   
   private var imageType:String = "JPEG";
   
   private var imageTypeArray : ArrayCollection = new ArrayCollection([
    {label : "jpeg", data: 'jpeg'},
    {label : "png", data: 'png'},
    {label : "gif", data: 'gif'}
   ]);
   
   private var bitmapData:BitmapData;
   
   private function init():void{
    draw();
   }
   var bitmap:Bitmap;
   private function draw():void{
    var canvas:Sprite = new Sprite();
    var bitmapData:BitmapData = new BitmapData(500, 500, false, 0xffffffff);
    bitmap = new Bitmap(bitmapData);
    bitmapData.fillRect(new Rectangle(0,0,100,100), 0x000000);
    bitmapData.fillRect(new Rectangle(100,10,200,200), 0x000000);
    canvas.addChild(bitmap);
    content.addChild(canvas); 
   }
      
   private function saveImage():void
   {
    var imageEncoder:IImageEncoder;
    var gifImageEncoder : GIFEncoder;
    if(imageType.toUpperCase() == "JPEG") imageEncoder = new JPEGEncoder(); 
    else if(imageType.toUpperCase() == "PNG") imageEncoder = new PNGEncoder();
    else if(imageType.toUpperCase() == "GIF") gifImageEncoder = new GIFEncoder();
    var byteArray:ByteArray;
    if(imageType.toUpperCase() == "GIF" ){
     gifImageEncoder.start();
     gifImageEncoder.setRepeat(0);
     gifImageEncoder.addFrame(bitmap.bitmapData);
     gifImageEncoder.finish();
     byteArray = gifImageEncoder.stream;
    }else{
     byteArray = imageEncoder.encode(bitmap.bitmapData);
    }    
    var fileName:String = "desiredfilename." + imageType; //저장할 파일 이름이다. 아무거나 적자!
    
    byteArray.position=0;
    var fr:FileReference = new FileReference();
    fr.addEventListener(Event.COMPLETE, eventSaveComplete);
                fr.save(byteArray, fileName );
    /*
    var uploadPath:String = "/servlet/FlexUpload"
    var parameters:URLVariables = new URLVariables();
    parameters.method = "id";
    parameters.userId = "2000321";
    
    var urlRequest:URLRequest = new URLRequest();
    urlRequest.url = uploadPath;
    urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
    urlRequest.method = URLRequestMethod.POST;
    urlRequest.data = UploadPostHelper.getPostData(fileName, byteArray, null ,parameters);
    urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
    
    //var encoder : Base64Encoder = new Base64Encoder();
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onComplate);
    urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
    urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
    urlLoader.load(urlRequest);
    */
   }
   
   private function eventSaveComplete(e:Event):void{
    trace("완료");
   }
   
   private function onComplate(e:Event):void{
    var loader:URLLoader = URLLoader(e.target);
    var bytedata:ByteArray = loader.data;
    var strData:String = bytedata.toString();
    trace( strData)
   }
   
   private function onError(e:ErrorEvent):void{
    trace('error');
   }
   
   /**
    * 페이지 인쇄
    **/
   private function printPage():void {
             var myPrintJob:PrintJob = new PrintJob();
             var options:PrintJobOptions = new PrintJobOptions();
             options.printAsBitmap = true;
             myPrintJob.start();
             try {
                 myPrintJob.addPage(content, null, options);
             }
             catch(e:Error) {
                 trace ("Had problem adding the page to print job: " + e);
             }
             try{
              myPrintJob.send();
             }catch (e:Error) {
                 trace ("Had problem printing: " + e);   
             }
         }
        
         private function changeImageTypeHandler(e:Event):void{
          imageType = ComboBox(e.target).selectedItem.data;
         }
  ]]>
 </mx:Script>
 <mx:Canvas width="100%" height="100%">
  <mx:UIComponent id="content" />
  <mx:ControlBar width="100%">
   <mx:Button label="print" click="printPage()"/>
   <mx:ComboBox id="imageCombo" dataProvider="{imageTypeArray}" change="changeImageTypeHandler(event)"/>
   <mx:Button label="image save" click="saveImage()"/>
  </mx:ControlBar>
 </mx:Canvas>
</mx:Application>

소스파일))


Flex 상에서 stage를 호출할 경우 null로 인식이 되어 속성을 찾지 못하는 경우는 현재 객체가 stage에 addChild 되어 있지 않은 경우이므로 addChild(객체)로 하신 후에 인식이 값을 가져와야 한다.

public function Sample()
{
addEventListener(Event.ADDED_TO_STAGE, init);



public function init(e:Event=null)
{
   //to do
    //trace(stage.width);
}


Flex 기본 배경색을 변경하는 방법이다. 세가지 방법이 있는데 Ant MXMLC, FlexBuilder, SWF MetaData로 변경을 할 수가 있다. 매번 잊어버리니 메모를 해둬야 겠다.

Ant MXMLC
<mxmlc>
    <default-background-color>0xFFFFFF</default-background-color>   
</mxmlc>

Flex Builder -> Project Properties -> Compiler Options -> Additional compiler arguments:
-default-background-color #FFFFFF

SWF MetaData
[SWF( backgroundColor="#FFFFFF" )]

출처 : http://www.webappsolution.com/wordpress/2009/11/04/flex-default-background-color-ant-mxmlc-flexbuilder/

기본적으로 Bitmap 인스턴스는, 참조하고 있는 BitmapData 객체에 setPixcel32()나 setPixel()이 호출되는 상황을 알아챈다.
비트맵의 모든 픽셀의 색상을 바꾸게 될 경우 setPixcel32()나 setPixcel()이 한프레임에서 자주 호출될때는 퍼포먼스가 떨어지게 되는데 이런경우 퍼포먼스 향상을 위해 lock()을 사용한다.

lock()을 호출하게 되면 AS는 Bitmap 객체가 setPixel32()나 setPixcel()의 실행을 알 수 없게 강제로 막는다.
그래서 연속된 setPixcel()이 호출되는 경우는 lock()을 호출하는 편이 좋다. 호출된 후 변경하려던 모든 픽셀이 변경이 완료된 경우는 unlock()을 호출해주면 Bitmap 객체가 모든 알림을 받을 수 있게 된다. 


var bitmapData:BitmapData = new BitmapData(1024, 1024, false);
var bmp:Bitmap = new Bitmap(bitmapData);
 
//퍼포먼스 향샹을 위해 lock을 걸어준다.
bitmapData.lock();    
    
for(var i:uint = 0; i < bitmapData.height; i++){
    for(var j:uint = 0; j < imgData.width; j++){
        bitmapData.setPixel(j, i, Math.floor(Math.random()*0xffffffff));
    }
}

bitmapData.unlock(); //lock 해제
 
container.addChild(bmp);

 
   private var urlDataLoader:URLLoader;

   //---------------------------------------------------------------
   // xml 형식의 파일을 불러온다.
   //----------------------------------------------------------------
   var dataRequest:URLRequest = new URLRequest("gshhs_l_data.xml");
   urlDataLoader = new URLLoader();
   urlDataLoader.addEventListener(Event.COMPLETE, loadDatasXML);
   urlDataLoader.load(dataRequest);
   
   
   
   //----------------------------------------------------------------
   // txt 형식의 파일을 불러온다.
   //----------------------------------------------------------------
   var requestConfig:URLRequest = new URLRequest("bdy_config.txt");
   var loaderConfig:URLLoader = new URLLoader();
   loaderConfig.addEventListener(Event.COMPLETE, completeConfigHandler);
   loaderConfig.load(requestConfig);



/**
   * configXML 설정파일 xml을 셋팅한다.
   */
  private function loadDatasXML(e:Event):void
  {
         //dataXML = new XML(e.target).children();
         dataXML = new XML(urlDataLoader.data).children();
         //trace(dataXML.length());
         //draw();
         // todo..
 
  }
 
private function completeConfigHandler(e:Event):void
{
    var src:String = e.target.data as String;
    tempConfigRowArray = src.split("\n");
    //mainHeaderConfigRowArray = tempConfigRowArray[0].split(",");
    //trace("config row count::" + tempConfigRowArray.length);
    //etc. etc.
}


데이터 바인딩식의 소스로서 사용할 수 있는 프롭퍼티를 식별합니다

프로퍼티가 데이터 바인딩식의 소스인 경우, Flex는 소스 프로퍼티의 변경시에 자동적으로 소스 프로퍼티의 값을 행선지 프로퍼티에 카피합니다.
다만, 카피를 실행하는 듯 Flex 에 통지하기 위해서는 [Bindable] 메타데이터태그를 사용해 프로퍼티를 Flex 에 등록해 소스 프로퍼티로부터 이벤트를 송출할 필요가 있습니다.

[Bindable] 메타데이터태그의 문장구조법은 다음과 같습니다.

[Bindable]
[Bindable(event="eventname")]

이벤트명을 생략 하면, Flex는 자동적으로 propertyChange라는 이름의 이벤트를 생성합니다.

데이터 바인딩 및 이 메타데이터태그에 대해 자세한 것은,데이터 바인딩을 참조해 주세요.


바인드 가능 프로퍼티 체인의 사용

데이터 바인딩의 소스로서 프로퍼티를 지정하면 그 프로퍼티의 변경 뿐만이 아니라 그 프로퍼티가 포함되는 프로퍼티 체인도 감시됩니다. 행선지 프로퍼티를 포함한 프로퍼티의 체인 전체는 「바인드 가능 프로퍼티 체인」이라고 불립니다.
다음의 예의 firstName.text는  firstName 오브젝트와 그 text 프로퍼티를 포함한 바인드 가능 프로퍼티 체인입니다.
 <first>{firstName.text}</first>

바인드 가능 프로퍼티 체인내의 지정한 프로퍼티가 변경되었을 경우에는 이벤트를 생성할 필요가 있습니다. 프로퍼티가 [Bindable] 메타데이터태그에 의해서 마크 되고 있는 경우는 Flex 컴파일러에 의해서 자동적으로 이벤트가 생성됩니다.

다음의 예는 변수 및 getter 프로퍼티에 대해서 [Bindable] 메타데이터태그를 사용하고 있습니다. 또한 이 예는 dispatchEvent() 함수를 호출하는 방법도 나타내 보이고 있습니다.

 [Bindable]
public var minFontSize:Number = 5;

[Bindable("textChanged")]
public function get text():String {
    return myText;
}

public function set text(t : String):void {
    myText = t;
    dispatchEvent( new Event( "textChanged" ) );
}

[Bindable] 메타데이터태그로 이벤트명을 생략 했을 경우는 Flex 컴파일러에 의해서 propertyChange라는 이름의 이벤트가 자동적으로 생성되어 송출되기 위해, 프로퍼티를 데이터 바인딩식의 소스로서 사용할 수 있습니다.

또, 오브젝트를 기존의 형태에 캐스트 하는 것에 의해서 오브젝트에 관한 구체적인 정보를 컴파일러에 제공할 필요가 있습니다.
다음의 예에서는,List 컨트롤의 myList 에 Customer 오브젝트가 포함되어 있으므로,selectedItem 프로퍼티는 Customer 오브젝트에 캐스트 됩니다.
 <mx:Model id="selectedCustomer">
    <customer>
        <name>{Customer(myList.selectedItem).name}</name>
        <address>{Customer(myList.selectedItem).address}</address>
        ...
    </customer>
</mx:Model>

경우에 따라서는, 바인딩이 의도한 대로 자동적으로 실행되지 않는 것이 있습니다.
다음의 예 처럼, dataProvider 프로퍼티의 아이템 전체를 변경했을 경우 바인딩은 자동적으로는 실행되지 않습니다.
 dataProvider[i] = newItem

또, 다음의 예 처럼, 프로퍼티의 서브 프로퍼티가 [Bindable] 메타데이터를 가지는 경우도 바인딩은 자동적으로는 실행되지 않습니다.
 ...
[Bindable]
var temp;
// Binding is triggered:
temp = new Object();
// Binding is not triggered, because label not a bindable property
// of Object:
temp.label = foo;
...

이 코드예에서는 {temp.label} 에 관해서 temp 하지만 Object 인 것이 문제입니다. 이 문제는 다음의 몇개의 방법으로 해결할 수 있습니다.
  • Object 의 초기화 사전 처리를 실시합니다.
  • ObjectProxy를 temp 에 할당합니다.ObjectProxy 의 프로퍼티는 모두 바인드 가능합니다.
  • temp를, 바인드 가능한 label 프로퍼티를 사용하고, 엄밀하게 형태 지정된 오브젝트로 합니다.
mouseX 프로퍼티 등 Flash Player 에 의해서 자동적으로 갱신되는 프로퍼티에 데이터를 바인딩 하는 경우에도 바인딩은 자동적으로는 실행되지 않습니다.

UIComponent 클래스의 executeBindings() 메소드는 UIComponent 오브젝트를 행선지로 하는 모든 바인딩을 실행합니다.Repeater 컴퍼넌트를 포함한 모든 컨테이너 및 컨트롤은 UIComponent 클래스를 확장한 것입니다. Container 클래스 및 Repeater 클래스의 executeChildBindings() 메소드는 Container 클래스 또는 Repeater 클래스의 아이 UIComponent 컴퍼넌트를 행선지로 하는 모든 바인딩을 실행합니다. 컨테이너는 모두 Container 클래스를 확장한 것입니다.

이러한 메소드에 의해 의도한 대로 행해지지 않는 바인딩을 실행할 수 있습니다. 변경을 더해도 바인딩이 실행되지 않는 경우에 유저 인터페이스를 갱신하려면 executeChildBindings() 메소드에의 호출등의 코드를 1 행 추가합니다. 다만 executeBindings() 메소드는 바인딩이 자동적으로 실행되지 않는 것을 알 수 있고 있는 경우에게만 사용합니다. 
 

이벤트의 MXML 프롭퍼티와 컴퍼넌트가 생성하는 이벤트 오브젝트의 데이터형을 정의하려면 [Event] 메타데이터태그를 사용합니다. [Event] 메타데이터태그는,ActionScript 파일내의 클래스 정의 전, 또는 MXML 파일내의 <mx:Metadata> 블록에 삽입합니다.

 커스텀 이벤트의 정의 방법에 대해 자세한 것은,커스텀 이벤트(을)를 참조해 주세요.

 [Event] 메타데이터태그의 문장구조법은 다음과 같습니다.

 [Event(name="eventName", type="package.eventType")]

 다음의 표에,[Event] 메타데이터태그의 프롭퍼티를 나타냅니다.

 프롭퍼티  형  설명
 eventName  String  패키지명을 포함한 이벤트명을 지정합니다.
 eventType  String  이벤트 오브젝트의 데이터형을 정의하는 클래스를 지정합니다.클래스명은 기본 이벤트 클래스의 Event 또는 Event 클래스의 서브 클래스의 어딘가에 됩니다.클래스명에는 패키지를 포함할 필요가 있습니다.

 다음의 예에서는, 컴퍼넌트를 송출할 수 있는 이벤트로서 myClickEvent 이벤트를 지정해 있습니다.

 [Event(name="myClickEvent", type="flash.events.Event")]

 

[Event] 메타데이터태그를 사용해 클래스 파일에 이벤트를 지정하지 않고, MXML 안에서 그 이벤트명을 사용하려고 하면 MXML 컴파일러에 의해 에러가 생성됩니다. [Event] 메타데이터태그를 생략 했을 경우에서도 addEventListener() 메소드를 사용하면 컴퍼넌트는 ActionScript 안의 이벤트의 이벤트 청취자를 등록할 수 있습니다.

 

다음의 예에서는 ActionScript 컴퍼넌트를 송출할 수 있는 이벤트로서 myClickEvent 이벤트를 지정해 있습니다.

[Event(name="myEnableEvent", type="flash.events.Event")]
public class MyComponent extends UIComponent
{
    ...
}

 

다음의 예는 MXML 파일내의 <mx:Metadata> 태그 안의 [Event] 메타데이터태그를 나타내고 있습니다.

 <?xml version="1.0"?>
<!-- TextAreaEnabled.mxml -->
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Metadata>
        [Event(name="myEnableEvent", type="flash.events.Event")]
    </mx:Metadata>

    ....

</mx:TextArea>


'DEVELOPMENT > FLEX & AIR' 카테고리의 다른 글

[actionscript 3.0] 외부 xml 및 txt 파일 읽기  (0) 2010.07.07
Bindable 메타 데이터 태그  (0) 2010.06.18
Style 메타데이터태그  (0) 2010.06.18
[Flex] 사용자 컴포넌트  (0) 2010.06.15
BlazeDS 4 출시  (0) 2010.06.11

컴포넌트의 스타일을 정의 할때 쓰이는 메타데이터 태그로, Flex Bulider에서 코드 힌트에 보이고 CSS에서 스타일 시트로 정의 가능한 메타 데이터 입니다.

 [Style] 메타데이터태그의 문장구조법은 다음과 같습니다.

 [Style(name="style_name"[,property="value",...])]

 메타 데이터가 들어가는 위치는 mxml 컴포넌트 파일의 경우 <mx:MetaData></mx:MetaData>의 테그 사이에 들어가게 되고 actionscript 컴포넌트 파일의 경우 패키지 선언과 클래스 선언 사이에 쓰이게 된다. (import 가 들어가는 위치랑 같음 )

 [Style] 메타데이터 태그의 프로퍼티값들

* name (String)

   : (필수) 스타일의 이름을 지정합니다.

* type (String)

   : 스타일 프로퍼티에 쓰는 값의 데이터 형을 지정합니다. Number나 Date등의 형태도 들어가고 packageName.className 형태의 데이터도 들어갑니다.

* arrayType (String)

   : type의 값이 Array 일 경우, Array 안에 들어가는 데이터 형을 정의 합니다. type값과 같이 데이터형과 클래스 형태도 들어갑니다.

* format (String)

   : 프로퍼티의 단위를 지정합니다. 예를들면 Type으로 Number를  지정한 경우는 format="Length"를 지정해서 스타일의 길이를 픽셀 단위로 정의 할 수 있습니다. 또는 Type으로 uint 를 지정하는 경우는 format="color"를 설정하면 RGB 칼라로 정의 할 수 있습니다.

* enumeration (String)

   : 스타일 프로퍼티에 들어갈수 있는 값들을 열거 합니다.  예를들면 BorderStyle의 경우 enumeration="inset,outset,solid,none" 식으로 값이 들어갑니다.

* inherit (String)

   : 프로퍼티를 계승 할지 지정합니다. 들어갈수 있는값은 yes, no 입니다. 여기서 계승은 객체 지향의 계승이 아니라 css 상의 계승을 의미합니다.  Global로 설정한것 또는 해당 컴포넌트에 전체로 스타일을 먹인것 (Panel, Button 형식으로)을 계승 할지 입니다.

* states (String)

   : 스킨 프로퍼티에 대해서, 스타일을 사용 할 수 있도록 지정해서 복수 상태를 가지는 컴포넌트에 스테이트 풀 스킨을 지정합니다. 예를 들면 버튼의 경우에는

states="up,over,down,disabled, selectedUp, selectedOver, selectedDown,selectedDisabled"의 값이 지정 됩니다.

 다음의 예는 TileList나 Grid 등에서 격자로 나오는 색상의 스타일 정의 입니다.

[Style(name="alternatingItemColors", type="Array", arrayType="uint", format="Color", inherit="yes")]

해당 스타일 값을 받을 때 : getStyle("style_name");
해당 스타일 값을 설정 할떄 : setStyle("style_name", "value");


'DEVELOPMENT > FLEX & AIR' 카테고리의 다른 글

Bindable 메타 데이터 태그  (0) 2010.06.18
Event 메타데이터 태그  (0) 2010.06.18
[Flex] 사용자 컴포넌트  (0) 2010.06.15
BlazeDS 4 출시  (0) 2010.06.11
[AIR] 플렛폼 독립적인 공통 디렉터리  (0) 2010.05.12