XY 행렬형태의 배치에서 includeInLayout과 visible을 활용하여 위와 같이 화면 배치를 조절할 수 있습니다.
아래 코드를 참조하여 다양한 형태로 메뉴구성을 조절 한다면 멋질거 같네요 ^^
소스코드보기 ▼
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Button;
private function screenChecker(targetRow:HBox):void{
//해당 라인 항목이 다 지워졌는지 확인하기
var hideRow:Boolean = true;
for(var i:uint=0;i<targetRow.numChildren;i++){
var tmpBox:Box = targetRow.getChildAt(i) as Box;
if(tmpBox.includeInLayout) {
hideRow = false;
break;
}
}
if(hideRow) { //해당 ROW의 모든 항목이 지워진 경우에는 해당 ROW를 지운다.
targetRow.includeInLayout = false;
targetRow.visible = false;
}else{
targetRow.includeInLayout = true;
targetRow.visible = true;
}
//모든 항목이 다 지워졌는지 확인하기
var hideAll:Boolean = true;
for(var j:uint=0;j<contents.numChildren;j++){
var tmpContents:HBox = contents.getChildAt(j) as HBox;
if(tmpContents.includeInLayout) {
hideAll = false;
break;
}
}
if(hideAll) { //모든 항목이 지워진 경우에는 contents를 제거한다.
contents.includeInLayout = false;
contents.visible = false;
}else{
contents.includeInLayout = true;
contents.visible = true;
}
}
private function openHandler(e:MouseEvent):void{
var target:Button = e.currentTarget as Button;
//테스트용은 9이하로 제작 : 안그럼 범위를 벗어남.
var rowNum:uint = Number(target.id.charAt(1));
var colNum:uint = Number(target.id.charAt(2));
//선택 항목을 화면에서 보여주기
var targetRow:HBox = contents.getChildAt(rowNum) as HBox;
var targetBox:Box = targetRow.getChildAt(colNum) as Box;
targetBox.includeInLayout = true;
targetBox.visible = true;
//메뉴에서 활성화 버튼 제거하기
for(var i:uint=0;i<menu.numChildren;i++){
var tmpBtn:Button = menu.getChildAt(i) as Button;
if(tmpBtn.id == "m"+rowNum+colNum) {
menu.removeChildAt(i);
break;
}
}
//화면 체크
screenChecker(targetRow);
}
private function closeHandler(e:MouseEvent):void{
var target:Button = e.currentTarget as Button;
//테스트용은 9이하로 제작 : 안그럼 범위를 벗어남.
var rowNum:uint = Number(target.id.charAt(1));
var colNum:uint = Number(target.id.charAt(2));
//선택 항목을 화면에서 지우기
var targetRow:HBox = contents.getChildAt(rowNum) as HBox;
var targetBox:Box = targetRow.getChildAt(colNum) as Box;
targetBox.includeInLayout = false;
//메뉴에서 활성화 버튼 추가하기
var menuBtn:Button = new Button;
menuBtn.label = "SHOW "+rowNum+colNum;
menuBtn.id = "m"+rowNum+colNum;
menuBtn.setStyle("fillColors",[0xffffff,targetBox.getStyle("backgroundColor")]);
menuBtn.addEventListener(MouseEvent.CLICK,openHandler);
menu.addChild(menuBtn);
요즘 실시간 모니터링 관련 DASHBOARD를 만들고 있는데.. 관련하여 차트를 만들고 있습니다.
1. RO를 통한 데이터 수신
// 2초단위 작업 시 발생 어러 ConcurrentModificationException
//
// [참조] 실제 개수 = 개수 * 서버수(10) * 자료수(3)
//
// 시간(초) 서버 개수 결과 RO 수신시간
// 2,000 10 43200 ERROR -
// 4,000 10 21600 OK 9.359
// 10,000 10 8640 OK 3.531
// 20,000 10 4320 OK 1.688
// 30,000 10 2880 OK 1.172
// 60,000 10 1440 OK 0.578
//
// 작업 진행은 시간 계산이 편한 10초 단위로 진행함.
위 표를 보면 알 수 있듯이 너무 많은 량의 데이터를 수신하려 한다면 flex messaging 처리 부분에서 힙 메모리 오버 플로우 애러가 발생하네요. 그래서 어쩔 수 없이 데이터를 줄여서 처리 했습니다. 맨 위 삽입한 차트가 1분(60초) 단위로 처리한 데이터를 RO를 통해 한번에 수신한 것인데 ... 그래도 차트 자체가 빡빡하네여 실제 적용할 때에는 20~30분 단위로 처리한다음 구간 SELECT 형태로 바꿔야 깔끔한 처리가 가능할 거 같습니다.
2. message-push 를 통한 데이터 수신 처리
RO를 통해 오늘-어제 데이터를 수신한 다음 실시간 데이터를 넣으면서 어제 데이터를 오늘 날짜로 업데이트 하는 형태의 차트 입니다. 위와 같이 처리를 하려 하니 차트 업데이트 과정에서 약간의 시간 지연 현상이 발생하는 거 같더군요 데이터 량이 많아 그런지 ㅡ,.ㅡ;
그리고 제가 전에 한 blazeDS 관련 포스팅 . message-push 서비스 사용시 channel-definition 에서 properties가 존재하지 않으면 ie7, ie8 에서는 정상적으로 message-push가 동작하지 않는거 잊지 말기 바랍니다. 아마도 요거 버그 같은데 ... 뭐 물어볼 분도 없구 ㅡ,.ㅡ blazeDS관련 국내 커뮤니티는 찾기 힘든거 같네요 ^^
3. 결론
ㄱ. RO 사용시 많은 량의 데이터 수신은 속도 저하를 가져옴. 적절하게 필요한 데이터만 사용하자 !
ㄴ. Messaging 서비스는 다수의 데이터 서비스 사용시 설계를 잘 해야 된다.
(자바쪽에서 스레드 내부에서 메시지 생성시 타입, 데이터 형태로 메시지를 만들어 보내는것이 무난 하기는 한거 같음)
private const MAX_SRV:uint = 3;
[Bindable]
private var viewArr:ArrayCollection = new ArrayCollection; //실제 보여주는 데이터
private var rcvArr:ArrayCollection = new ArrayCollection; //받은 데이터
private var fndIdx:uint;
private var timer:Timer;
private function init():void{
timer = new Timer(1000);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerHandler);
}
private function cbHandler(e:Event):void{
generateRealValues();
}
private function generateRealValues():void{
//보여주려는 것
var tmpArr:ArrayCollection = new ArrayCollection;
for(var i:uint=0;i<MAX_SRV;i++){
var tmpCB:CheckBox = this["cb"+i] as CheckBox;
if(tmpCB.selected){
tmpArr.addItem(rcvArr.getItemAt(Number(tmpCB.id.substr(2))));
}
}
viewArr = tmpArr;
}
private function timerHandler(e:TimerEvent):void{
generateDummyValues();
}
private function generateDummyValues():void{
rcvArr.removeAll();
for(var i:uint=0;i<MAX_SRV;i++){
var op:ObjectProxy = new ObjectProxy();
op.server = "srv"+i; // label field
op.apple = randRange(0,5); // data field
op.melon = randRange(0,5);
op.banana = randRange(0,5);
rcvArr.addItem(op);
}
generateRealValues();
}
private function randRange(min:Number, max:Number):Number {
var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
return randomNum;
}
]]>
</mx:Script>
작업환경 : 이클립스 J2EE & FLEX 환경 (설치 참조 : http://wonsama.tistory.com/180 )
테스트 목적 : Remote Object를 확인하기 위해 테스트를 진행.
작업진행 : Eclipse에서 환경설정 및 클래스 생성 이후 Flex에서 해당 서비스 호출 소스 작성을 실시한다.
[Eclipse] // WEB-INF/flex/remoting-config.xml : 리모트 오브젝트 관련 환경을 설정한다.
RO를 사용하기 위하여 추가적으로 설정한 내용임.
1: destination id - FLEX에서 호출하는 RemoteObject의 destination 를 지정한다.
2: source - 참조하는 클래스 소스를 설정한다.
[Eclipse] // src/book/Employee.java
package book;
import java.io.Serializable;
public class Employee implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public String name;
public String phone;
public String email;
public Employee(){
<mx:RemoteObject id="emp" destination="empRO" showBusyCursor="true"
result="resultHandler(event)" fault="faultHandler(event)"/>
=> RO를 설정한 부분
=> destination : Eclipse에 설정된 클래스를 호출하기 위한 Destination
<mx:Button label="Get Employee List" click="emp.getList(dept.selectedItem.data)" />
=> RO를 호출하는 부분
=> emp.getList : getList 메소드를 호출한다. 처리 결과는 위에서 설정한 리스너를 통해 들어온다.
[처리 결과]
결론 및 요약 :
- [Eclipse] remoting-config.xml 설정 => 설정에 맞춰 클래스 생성 => [Flex] RO호출
- RO를 통해 처리를 JAVA로 위임한 이후 결과를 받아 처리 할 수 있음. 매우 유익한듯.