Flex PropertyGrid 实现


PropertyGrid在界面设计工具中是比较常用的组件,在.NET的WinForm设计中,PropertyGrid作为内置的组件来实现对 button、label等组件的属性设置,不仅满足了设计时的需要,还能够在运行时提供美观实用的帮助;但是Flex作为目前界面设计展现方向上的主流技术,并没有提供该组件。为了弥补这一不足,本文将介绍并实现Flex PropertyGrid组件模型。

  PropertyGrid模型可以分为两个部分,即行为模型和数据展现模型。

  所谓的行为模型就是PropertyGrid所包含的事件及其在不同状态下的展示方式。事件部分我们暂且只支持PropertyGrid的 selectedObjectChanged事件。展示方式主要是悬浮状态下,Mini选项卡开启,鼠标移到Mini选项卡的时候 PropertyGrid主面板弹出,鼠标移出PropertyGrid时,PropertyGrid自动关闭,同时显示出Mini选项卡,;非悬浮状态下,PropertyGrid停靠在Container中,Mini选项卡关闭。

  数据展现模型就是PropertyGrid所展示内容的元数据定义,用这些定义好的元数据标记数据类型后,PropertyGrid可以自动的从数据类型实例中读取元数据定义,并根据类别、描述等信息自动展示。

  事件模型处理相关代码如下:

[Event(name="selectedObjectChanged",type="propertygrid.PropertyGridEvent")] 
    [Event(name="floatStateChanged",type="propertygrid.PropertyGridEvent")]; 
    public class IPropertyGrid extends Canvas 
    { 
        //是否悬浮 
        private var isFloat:Boolean=false; 
        //悬浮状态需要的mini属性卡 
        private var miniPropertyGird:Canvas=null; 
        //当前选择对象 
        private var selectedObject:Object=null; 
         
        //属性窗口容器 
        public var container:DisplayObjectContainer=null; 
        //属性窗口内容展示区 
        public var content:VBox=null; 
        //悬浮状态切换图片 
        public var title_img_pin:Image=null; 
        //最小化图片 
        public var title_img_min:Image=null; 
         
        /** 
         * 构造函数 
         * */ 
        public function IPropertyGrid() 
        { 
            this.addEventListener(FlexEvent.CREATION_COMPLETE,init); 
            this.addEventListener(PropertyGridEvent.FLOAT_STATE_CHANGED,floateStateChangedHandler); 
        } 
         
        /** 
         * 悬浮状态切换的处理函数 
         * 
         * 逻辑:悬浮状态,从容器中移除属性窗口,将mini属性窗口增加到容器中,同时为属性窗口增加Rollout处理函数 
         *         内嵌状态,将属性窗口增加到容器,从容器中mini属性窗口,移除属性窗口的Rollout处理函数 
         * */ 
        public function floateStateChangedHandler(e:PropertyGridEvent):void 
        { 
            if(isFloat) 
            { 
                this.container.removeChild(this); 
                this.container.addChild(miniPropertyGird); 
                this.addEventListener(MouseEvent.ROLL_OUT,mouseClosePropGrid); 
            } 
            else 
            { 
                this.container.addChild(this); 
                this.container.removeChild(miniPropertyGird); 
                this.removeEventListener(MouseEvent.ROLL_OUT,mouseClosePropGrid); 
            } 
        } 
         
        /** 
         * 获取当前选中对象 
         * */ 
        public function get SelectedObj():Object 
        { 
            return this.selectedObject; 
        } 
         
        /** 
         * 更改当前选中对象,并触发SELECTED_OBJECT_CHANGED事件 
         * */ 
        public function set SelectedObj(obj:Object):void 
        { 
            if(this.selectedObject!=obj) 
            { 
                this.selectedObject=obj; 
                dispatchEvent(new PropertyGridEvent(PropertyGridEvent.SELECTED_OBJECT_CHANGED)); 
            } 
        } 
         
        /** 
         * 初始化函数 
         * */ 
        public function init(e:FlexEvent):void 
        { 
            Assert.notNull(container,"container"); 
            Assert.notNull(content,"content"); 
            Assert.notNull(title_img_pin,"title_img_pin"); 
            Assert.notNull(title_img_min,"title_img_min"); 
            title_img_pin.addEventListener(MouseEvent.CLICK,changeFloatState); 
            title_img_min.addEventListener(MouseEvent.CLICK,minPropertyGrid); 
            initMiniPropertyGrid(); 
        } 
                 
        /** 
         * 更改悬浮状态函数 
         * */ 
        public function changeFloatState(e:MouseEvent):void 
        { 
            this.isFloat=!this.isFloat; 
            dispatchEvent(new PropertyGridEvent(PropertyGridEvent.FLOAT_STATE_CHANGED)); 
        } 
         
        /** 
         * 悬浮状态下显示属性窗口函数 
         * */ 
        public function showPropertyGrid(e:MouseEvent):void 
        { 
            var point:Point=new Point(container.x+container.width-this.width,container.y); 
            var targetPoint:Point=container.localToGlobal(point); 
            this.x=targetPoint.x; 
            this.y=targetPoint.y; 
            this.height=container.height; 
            PopUpManager.addPopUp(this,container,false); 
            var effect:WipeLeft=new WipeLeft(); 
            effect.duration=300; 
            effect.target=this; 
            effect.play(); 
        } 
         
        /** 
         * 初始化mini属性窗口 
         * */ 
        public function initMiniPropertyGrid():void 
        { 
            miniPropertyGird=new Canvas(); 
            miniPropertyGird.height=100; 
            miniPropertyGird.width=25; 
            miniPropertyGird.setStyle("top",0); 
            miniPropertyGird.setStyle("right",0); 
            var img:Image=new Image(); 
            img.source="assets/propertygrid.png"; 
            img.percentHeight=100; 
            img.percentWidth=100; 
            img.addEventListener(MouseEvent.MOUSE_OVER,showPropertyGrid); 
             
            miniPropertyGird.addChild(img); 
        } 
         
        /** 
         * 最小化属性窗口函数 
         * */ 
        public function minPropertyGrid(e:MouseEvent):void 
        { 
            PopUpManager.removePopUp(this); 
        } 
         
        /** 
         * 关闭悬浮状态属性窗口处理函数 
         * */ 
        public function mouseClosePropGrid(e:MouseEvent):void 
        { 
            var pg:IPropertyGrid=e.target as IPropertyGrid; 
            if(pg!=null) 
            { 
                PopUpManager.removePopUp(pg); 
            } 
        } 
         
        /** 
         * 增加属性窗口单元 
         * 
         * @param title:单元标题 
         * */ 
        public function addGridUnit(title:String):GridUnit 
        { 
            var tgrid:GridUnit=new GridUnit(); 
            PopUpManager.addPopUp(tgrid,Application.application.document); 
            tgrid.title_content.text=title; 
            this.content.addChild(tgrid); 
            return tgrid; 
        } 
    } 
 
    /** 
     * @desc:    属性窗口事件 
     *     SELECTED_OBJECT_CHANGED    :    当前选中对象改变时触发的事件 
     *     FLOAT_STATE_CHANGED        :    悬浮状态发生改变时触发的事件 
     * 
     * @author:    sunjingtao 
     * */ 
    public class PropertyGridEvent extends Event 
    { 
        public static const SELECTED_OBJECT_CHANGED:String="selectedObjectChanged"; 
        public static const FLOAT_STATE_CHANGED:String="floatStateChanged"; 
        public function PropertyGridEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) 
        { 
            super(type, bubbles, cancelable); 
        } 
         
    } 
数据模型部分想要做好就比较复杂,但是主要就是反射相关知识以及元数据的使用。

  反射:describeType函数

  元数据:编译时增加编译参数-keep-as3-metadata+=MetaData1,MetaData2…

  使用:

  假设我们对以下对象进行属性设置:

    public class Activity 
    { 
        [Appearance(name="imageSource",description="图像资源")] 
        public var ImageSource:String; 
         
        [Behavior(name="do1",description="行为")] 
        public var DoEvent1:String; 
         
        [Behavior(name="do2",description="行为")] 
        public var DoEvent2:String; 
         
        public var Test:String; 
         
        public function Activity(source:String,doEvent:String) 
        { 
            this.ImageSource=source; 
            this.DoEvent1=doEvent+"11"; 
            this.DoEvent2=doEvent+"22"; 
        } 
    } 

  主程序为:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    xmlns:propertygrid="ui.propertygrid.*"> 
<mx:Script> 
    <![CDATA[ 
        import datastructure.Map; 
        import mx.managers.PopUpManager; 
        import ui.propertygrid.GridUnit; 
        import mx.controls.Label; 
        import mx.containers.GridItem; 
        import mx.containers.GridRow; 
        import mx.collections.ArrayCollection; 
        import reflect.MetaDataInfo; 
        import reflect.MetaData; 
        import mx.containers.FormItem; 
        import reflect.Variable; 
        import reflect.InstanceInfo; 
        import flash.utils.describeType; 
        import xdesigner.Activity; 
        private function doParse():void 
        { 
            var act:Activity=new Activity("source","doEvent"); 
            var instance:MetaDataInfo=new MetaDataInfo(act); 
            for each(var key:String in instance.Keys) 
            { 
                var tgrid:GridUnit=propgrid.addGridUnit(key); 
                for each(var obj:Object in instance.getMetaDataRefObjs(key)) 
                { 
                    if(obj is Variable) 
                    { 
                        var variable:Variable=obj as Variable; 
                        var map:Map=new Map(); 
                        map.push("text",variable.Value); 
                        tgrid.addRow(variable.Name,new Label(),map); 
                    } 
                } 
            } 
             
        } 
    ]]> 
</mx:Script> 
<mx:Canvas id="container" width="100%" height="100%"> 
    <mx:Canvas width="100%" height="100%" borderStyle="solid" borderColor="#F5F7F9"> 
        <propertygrid:PropertyGrid id="propgrid" container="{container}" x="81" y="31"> 
             
        </propertygrid:PropertyGrid> 
    </mx:Canvas> 
</mx:Canvas> 
<mx:Button label="Parse" click="doParse()"/> 
</mx:Application> 
显示效果:


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3