`
牧羊人
  • 浏览: 210763 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

FLEX 构建完美的带有CheckBox三状态的Tree控件

    博客分类:
  • flex
阅读更多
CheckTree.as
package ht.system.controls  
{  
    import mx.controls.Tree;  
    import mx.core.ClassFactory;  
    import mx.events.ListEvent;  
    /** 
     * 三状态复选框树控件 
     * <br /><br /> 
     */  
      
    public class CheckTree extends Tree  
    {  
        //数据源中状态字段  
        private var m_checkBoxStateField:String="@state";  
        //部分选中的填充色  
        [Bindable]  
        private var m_checkBoxBgColor:uint=0x009900;  
        //填充色的透明度  
        [Bindable]  
        private var m_checkBoxBgAlpha:Number=1;  
        //填充色的边距  
        [Bindable]  
        private var m_checkBoxBgPadding:Number=3;  
        //填充色的四角弧度  
        [Bindable]  
        private var m_checkBoxBgElips:Number=2;  
        //取消选择是否收回子项  
        [Bindable]  
        private var m_checkBoxCloseItemsOnUnCheck:Boolean=true;  
        //选择项时是否展开子项  
        [Bindable]  
        private var m_checkBoxOpenItemsOnCheck:Boolean=false;  
        //选择框左边距的偏移量  
        [Bindable]  
        private var m_checkBoxLeftGap:int=8;  
        //选择框右边距的偏移量  
        [Bindable]  
        private var m_checkBoxRightGap:int=20;  
        //是否显示三状态  
        [Bindable]  
        private var m_checkBoxEnableState:Boolean=true;  
        //与父项子项关联  
        [Bindable]  
        private var m_checkBoxCascadeOnCheck:Boolean=true;  
  
  
        //双击项目  
        public var itemDClickSelect:Boolean=true;  
  
        public function CheckTree()  
        {  
            super();  
            doubleClickEnabled=true;  
        }  
  
        override protected function createChildren():void  
        {  
            var myFactory:ClassFactory=new ClassFactory(CheckTreeRenderer);  
            this.itemRenderer=myFactory;  
            super.createChildren();  
            addEventListener(ListEvent.ITEM_DOUBLE_CLICK, onItemDClick);  
        }  
        public function PropertyChange():void  
        {  
            dispatchEvent(new ListEvent(mx.events.ListEvent.CHANGE));  
        }  
  
  
        /** 
         * 树菜单,双击事件 
         * @param evt 双击事件源 
         * 
         */  
        public function onItemDClick(e:ListEvent):void  
        {  
            if(itemDClickSelect)  
                OpenItems();  
        }  
  
        /** 
         * 打开Tree节点函数,被 有打开节点功能的函数调用 
         * @param item  要打开的节点 
         * 
         */  
        public function OpenItems():void  
        {  
            if (this.selectedIndex >= 0 && this.dataDescriptor.isBranch(this.selectedItem))  
                this.expandItem(this.selectedItem, !this.isItemOpen(this.selectedItem), true);  
        }  
          
        /** 
         * 数据源中状态字段 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxStateField():String  
        {  
            return m_checkBoxStateField;  
        }  
        public function set checkBoxStateField(v:String):void  
        {  
            m_checkBoxStateField=v;  
            PropertyChange();  
        }  
          
        /** 
         * 部分选中的填充色 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxBgColor():uint  
        {  
            return m_checkBoxBgColor;  
        }  
        public function set checkBoxBgColor(v:uint):void  
        {  
            m_checkBoxBgColor=v;  
            PropertyChange();  
        }  
          
        /** 
         * 填充色的透明度 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxBgAlpha():Number  
        {  
            return m_checkBoxBgAlpha;  
        }  
        public function set checkBoxBgAlpha(v:Number):void  
        {  
            m_checkBoxBgAlpha=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 填充色的边距 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxBgPadding():Number  
        {  
            return m_checkBoxBgPadding;  
        }  
        public function set checkBoxBgPadding(v:Number):void  
        {  
            m_checkBoxBgPadding=v;  
            PropertyChange();  
        }  
          
        /** 
         * 填充色的四角弧度 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxBgElips():Number  
        {  
            return m_checkBoxBgElips;  
        }  
        public function set checkBoxBgElips(v:Number):void  
        {  
            m_checkBoxBgElips=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 取消选择是否收回子项 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxCloseItemsOnUnCheck():Boolean  
        {  
            return m_checkBoxCloseItemsOnUnCheck;  
        }  
        public function set checkBoxCloseItemsOnUnCheck(v:Boolean):void  
        {  
            m_checkBoxCloseItemsOnUnCheck=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 选择项时是否展开子项 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxOpenItemsOnCheck():Boolean  
        {  
            return m_checkBoxOpenItemsOnCheck;  
        }  
        public function set checkBoxOpenItemsOnCheck(v:Boolean):void  
        {  
            m_checkBoxOpenItemsOnCheck=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 选择框左边距的偏移量 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxLeftGap():int  
        {  
            return m_checkBoxLeftGap;  
        }  
        public function set checkBoxLeftGap(v:int):void  
        {  
            m_checkBoxLeftGap=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 选择框右边距的偏移量 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxRightGap():int  
        {  
            return m_checkBoxRightGap;  
        }  
        public function set checkBoxRightGap(v:int):void  
        {  
            m_checkBoxRightGap=v;  
            PropertyChange();  
        }  
          
          
        /** 
         * 是否显示三状态 
         * @return  
         *  
         */       
        [Bindable]  
        public function get checkBoxEnableState():Boolean  
        {  
            return m_checkBoxEnableState;  
        }  
        public function set checkBoxEnableState(v:Boolean):void  
        {  
            m_checkBoxEnableState=v;  
            PropertyChange();  
        }  
          
          
          
        /** 
         * 与父项子项关联 
         * @return  
         *  
         */  
        [Bindable]  
        public function get checkBoxCascadeOnCheck():Boolean  
        {  
            return m_checkBoxCascadeOnCheck;  
        }  
        public function set checkBoxCascadeOnCheck(v:Boolean):void  
        {  
            m_checkBoxCascadeOnCheck=v;  
            PropertyChange();  
        }  
          
    }  
}  

CheckTreeRenderer.as
package ht.system.controls  
{  
    import <a title="<a title="<a title="<a title="Flash" href="http://" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>.events.MouseEvent;  
    import <a title="<a title="<a title="<a title="Flash" href="http://" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>.geom.Rectangle;  
    import <a title="<a title="<a title="<a title="Flash" href="http://" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>" href="http://" mce_href="../../undefined/" target="_blank">Flash</a>.xml.*;  
      
    import mx.collections.*;  
    import mx.controls.CheckBox;  
    import mx.controls.Tree;  
    import mx.controls.listClasses.*;  
    import mx.controls.treeClasses.*;  
    import mx.events.FlexEvent;  
    import mx.events.ListEvent;  
  
    /** 
     * 三状态复选框树控件 
     *  <br /><br /> 
     */   
    public class CheckTreeRenderer extends TreeItemRenderer  
    {  
        protected var myCheckBox:CheckBox;  
        /** 
         * STATE_SCHRODINGER : 部分子项选中 <br /> 
         * STATE_CHECKED :     全部子项选中 <br /> 
         * STATE_UNCHECKED :   全部子项未选中 <br /> 
         */  
        static private var STATE_SCHRODINGER:int=2;  
        static private var STATE_CHECKED:int=1;  
        static private var STATE_UNCHECKED:int=0;  
  
        private var myTree:CheckTree;  
  
        public function CheckTreeRenderer()  
        {  
            super();  
            mouseEnabled=true;  
  
        }  
  
        /** 
         * 初始化完成时处理复选框和图片对象 
         * 
         */  
        override protected function createChildren():void  
        {  
            myCheckBox=new CheckBox();  
            addChild(myCheckBox);  
            myCheckBox.addEventListener(MouseEvent.CLICK, checkBoxToggleHandler);  
              
            myTree = this.owner as CheckTree;  
              
            super.createChildren();  
              
            myTree.addEventListener(ListEvent.CHANGE,onPropertyChange);  
              
        }  
        protected function onPropertyChange(e:ListEvent=null):void  
        {  
            this.updateDisplayList(unscaledWidth,unscaledHeight);  
        }  
        /** 
         * // TODO : 递归设置父项目的状态 
         * @param item 项目 
         * @param tree 树对象 
         * @param state 目标状态 
         * 
         */  
        private function toggleParents(item:Object, tree:Tree, state:int):void  
        {  
            if (item == null)  
                return ;  
            else  
            {  
                var stateField:String=myTree.checkBoxStateField;  
                var tmpTree:IList=myTree.dataProvider as IList;  
                var oldValue:Number=item[stateField] as Number;  
                var newValue:Number=state as Number;  
                  
                item[myTree.checkBoxStateField]=state;  
                tmpTree.itemUpdated(item,stateField,oldValue,newValue);  
                  
                //item[myTree.checkBoxStateField]=state;  
                var parentItem:Object=tree.getParentItem(item);  
                if(null!=parentItem)  
                    toggleParents(parentItem, tree, getState(tree, parentItem));  
            }  
        }  
  
        /** 
         * // TODO : 设置项目的状态和子项的状态 
         * @param item 项目 
         * @param tree 树对象 
         * @param state 目标状态 
         * 
         */  
        private function toggleChildren(item:Object, tree:Tree, state:int):void  
        {  
            if (item == null)  
                return ;  
            else  
            {  
                var stateField:String=myTree.checkBoxStateField;  
                var tmpTree:IList=myTree.dataProvider as IList;  
                var oldValue:Number=item[stateField] as Number;  
                var newValue:Number=state as Number;  
                  
                item[myTree.checkBoxStateField]=state;  
                tmpTree.itemUpdated(item,stateField,oldValue,newValue);  
                  
                var treeData:ITreeDataDescriptor=tree.dataDescriptor;  
                if (myTree.checkBoxCascadeOnCheck && treeData.hasChildren(item))  
                {  
                    var children:ICollectionView=treeData.getChildren(item);  
                    var cursor:IViewCursor=children.createCursor();  
                    while(!cursor.afterLast)  
                    {  
                        toggleChildren(cursor.current, tree, state);  
                        cursor.moveNext();  
                    }  
                }  
            }  
        }  
  
        /** 
         * //TODO:获得parent的状态 
         * @param tree 树对象 
         * @param parent 目标项 
         * @return 状态 
         * 
         */  
        private function getState(tree:Tree, parent:Object):int  
        {  
            var noChecks:int=0;  
            var noCats:int=0;  
            var noUnChecks:int=0;  
            if (parent != null)  
            {  
                var treeData:ITreeDataDescriptor=tree.dataDescriptor;  
                var cursor:IViewCursor=treeData.getChildren(parent).createCursor();  
                while(!cursor.afterLast)  
                {  
                    if (cursor.current[myTree.checkBoxStateField] == STATE_CHECKED)  
                        noChecks++;  
                    else if (cursor.current[myTree.checkBoxStateField] == STATE_UNCHECKED)  
                        noUnChecks++;  
                    else  
                        noCats++;  
                    cursor.moveNext();  
                }  
            }  
  
            if ((noChecks > 0 && noUnChecks > 0) || noCats > 0)  
                return STATE_SCHRODINGER;  
            else if (noChecks > 0)  
                return STATE_CHECKED;  
            else  
                return STATE_UNCHECKED;  
        }  
  
        /** 
         * //TODO:设置项目的父项状态和子项状态 
         * @param event 事件 
         * 
         */  
        private function checkBoxToggleHandler(event:MouseEvent):void  
        {  
            if (data)  
            {  
                var myListData:TreeListData=TreeListData(this.listData);  
                var selectedNode:Object=myListData.item;  
                myTree=myListData.owner as CheckTree;  
                var toggle:Boolean=myCheckBox.selected;  
                if (toggle)  
                {  
                    toggleChildren(data, myTree, STATE_CHECKED);  
                    if (myTree.checkBoxOpenItemsOnCheck)  
                        myTree.expandChildrenOf(data, true);  
                }  
                else  
                {  
                    toggleChildren(data, myTree, STATE_UNCHECKED);  
                    if (myTree.checkBoxCloseItemsOnUnCheck)  
                        myTree.expandChildrenOf(data, false);  
                }  
                //TODO:如果所有子项选中时需要选中父项则执行以下代码  
                if (myTree.checkBoxCascadeOnCheck)  
                {  
                    var parent:Object=myTree.getParentItem(data);  
                    if(null!=parent)  
                        toggleParents(parent, myTree, getState(myTree, parent));  
                }  
            }  
            //myTree.PropertyChange();  
            //dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));  
        }  
  
        /** 
         * 设置本项的复选框状态 
         * @param checkBox 复选框 
         * @param value 
         * @param state 状态 
         * 
         */  
        private function setCheckState(checkBox:CheckBox, value:Object, state:int):void  
        {  
            if (state == STATE_CHECKED)  
                checkBox.selected=true;  
            else if (state == STATE_UNCHECKED)  
                checkBox.selected=false;  
            else if (state == STATE_SCHRODINGER)  
                checkBox.selected=false;  
        }  
  
        override public function set data(value:Object):void  
        {  
            if (value != null)  
            {  
                super.data=value;  
                setCheckState(myCheckBox, value, value[myTree.checkBoxStateField]);  
            }  
        }  
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void  
        {  
            super.updateDisplayList(unscaledWidth, unscaledHeight);  
            if (super.data)  
            {  
                if (super.icon != null)  
                {  
                    myCheckBox.x=super.icon.x + myTree.checkBoxLeftGap;  
                    myCheckBox.y=(height - myCheckBox.height) / 2;  
                    super.icon.x=myCheckBox.x + myCheckBox.width + myTree.checkBoxRightGap;  
                    super.label.x=super.icon.x + super.icon.width + 3;  
                }  
                else  
                {  
                    myCheckBox.x=super.label.x + myTree.checkBoxLeftGap;  
                    myCheckBox.y=(height - myCheckBox.height) / 2;  
                    super.label.x=myCheckBox.x + myCheckBox.width + myTree.checkBoxRightGap;  
                }  
                  
                setCheckState(myCheckBox, data, data[myTree.checkBoxStateField]);  
                if (myTree.checkBoxEnableState && data[myTree.checkBoxStateField] == STATE_SCHRODINGER)  
                {  
                    fillCheckBox(true);  
                    trace(myTree.checkBoxEnableState);  
                    trace(data[myTree.checkBoxStateField]);  
                }  
                else  
                    fillCheckBox(false);  
            }  
        }  
  
        protected function fillCheckBox(isFill:Boolean):void  
        {  
            myCheckBox.graphics.clear();  
  
            if (isFill)  
            {  
                var myRect:Rectangle=getCheckTreeBgRect(myTree.checkBoxBgPadding);  
                myCheckBox.graphics.beginFill(myTree.checkBoxBgColor, myTree.checkBoxBgAlpha)  
                myCheckBox.graphics.drawRoundRect(myRect.x, myRect.y, myRect.width, myRect.height, myTree.checkBoxBgElips, myTree.checkBoxBgElips);  
                myCheckBox.graphics.endFill();  
            }  
        }  
  
        protected function getCheckTreeBgRect(checkTreeBgPadding:Number):Rectangle  
        {  
            var myRect:Rectangle=myCheckBox.getBounds(myCheckBox);  
            myRect.top+=checkTreeBgPadding;  
            myRect.left+=checkTreeBgPadding;  
            myRect.bottom-=checkTreeBgPadding;  
            myRect.right-=checkTreeBgPadding;  
            return myRect;  
        }  
  
  
    } //end class  
} //end package  

test
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  
                xmlns:ns1="controls.*"  
                fontSize="12"  
                xmlns:controls="ht.system.controls.*"  
                 creationComplete="initApp()"  
                layout="horizontal" xmlns:ns2="flexlib.controls.*" xmlns:ns3="flexlib.containers.*" xmlns:ns4="ht.charts.controls.*" xmlns:ns5="ht.machine.views.*">  
    <mx:Script>  
        <!--[CDATA[  
            import mx.collections.*;  
            import ht.system.controls.*;  
  
            import mx.collections.ArrayCollection;  
            [Bindable]  
            public var arrarc:ArrayCollection=new ArrayCollection([  
                {state:0,label:"有效值"},  
                {state:0,label:"平均值"},  
                {state:0,label:"峰值"},  
                {state:0,label:"峰峰值"},  
                {state:0,label:"X1"},  
                {state:2,label:"频带",  
                    children:[  
                        {state:0, label:"频带1"},  
                        {state:1, label:"频带2"},  
                        {state:0, label:"频带3"},  
                        {state:0, label:"频带4"},  
                        {state:0, label:"频带5"},  
                    ]  
                }  
                ]);  
  
            [Bindable]  
            public var folderList:XMLList=  
                <>  
                    <folder state="0" label="Marketing Collateral">  
                        <folder state="0" label="Media,PR,and Communications" >  
                            <folder state="0" label="Article Reprint Disclaimers" />  
                            <folder state="0" label="Articles Reprints" />  
                            <folder state="0" label="Interviews and Transcripts" />  
                            <folder state="0" label="Press Kits" />  
                            <folder state="0" label="Press Releases" />  
                            <folder state="0" label="Quick Hits" />  
                            <folder state="0" label="Rep Talking Points" />  
                            <folder state="0" label="Special Updates" />  
                            <folder state="0" label="White Papers" />  
                        </folder>  
                        <folder state="0" label="Forms and Applications" >  
                            <folder state="0" label="Applications" />  
                            <folder state="0" label="Forms" />  
                        </folder>  
                    </folder>  
                </>  
            ;  
            [Bindable]  
            public var folderCollection:XMLListCollection;  
  
            override protected function initializationComplete():void  
            {  
                super.initializationComplete();  
                folderCollection=new XMLListCollection(folderList);  
            }  
            protected function initApp():void  
            {  
                this.callLater(test);  
            }  
            protected function test():void  
            {  
                        tree3.checkBoxOpenItemsOnCheck=true;  
                        tree3.checkBoxCascadeOnCheck=true;  
                        tree3.checkBoxEnableState=false;  
                        tree3.itemDClickSelect=true;  
                          
                        tree2.checkBoxOpenItemsOnCheck=true;  
                        tree2.checkBoxCascadeOnCheck=true;  
                        tree2.checkBoxEnableState=true;  
                        tree2.checkBoxBgColor=0x000000;  
            }  
        ]]-->  
    </mx:Script>  
    <mx:Panel width="166" height="100%" layout="absolute">  
        <mx:Form x="0" y="0" width="146" height="100%">  
            <mx:CheckBox label="取消收回子项" id="checkBoxCloseItemsOnUnCheck" selected="true"/>  
            <mx:CheckBox label="选中展开子项" id="checkBoxOpenItemsOnCheck"/>  
            <mx:CheckBox label="是否三状态" id="checkBoxEnableState" selected="true"/>  
            <mx:CheckBox label="是否关联父子" id="checkBoxCascadeOnCheck" selected="true"/>  
            <mx:FormItem label="样式" direction="vertical">  
                <mx:ColorPicker id="checkBoxBgColor" selectedColor="#009900"/>  
                <mx:HSlider width="61" id="checkBoxBgAlpha" allowTrackClick="true" minimum="0" maximum="1" snapInterval="0.1" value="1"/>  
            </mx:FormItem>  
            <mx:FormItem label="填充边距">  
                <mx:NumericStepper id="checkBoxBgPadding" value="3" minimum="0" maximum="6" stepSize="1"/>  
            </mx:FormItem>  
            <mx:FormItem label="填充弧度">  
                <mx:NumericStepper id="checkBoxBgElips" value="2" minimum="0" maximum="6" stepSize="1"/>  
            </mx:FormItem>  
            <mx:FormItem label="左边距">  
                <mx:NumericStepper id="checkBoxLeftGap" value="8" minimum="0" maximum="20" stepSize="1"/>  
            </mx:FormItem>  
            <mx:FormItem label="右边距">  
                <mx:NumericStepper id="checkBoxRightGap" value="20" minimum="0" maximum="40" stepSize="1"/>  
            </mx:FormItem>  
            <mx:CheckBox label="双击是否展开项" id="itemDClickSelect" selected="true"/>  
        </mx:Form>  
        <mx:ControlBar height="46" y="321">  
            <mx:ToggleButtonBar>  
              
    <mx:dataProvider>  
        <mx:Array>  
            <mx:String>Flash</mx:String>  
            <mx:String>Director</mx:String>  
            <mx:String>Dreamweaver</mx:String>  
            <mx:String>ColdFusion</mx:String>  
        </mx:Array>  
    </mx:dataProvider></mx:ToggleButtonBar>  
        </mx:ControlBar>  
    </mx:Panel>  
  
  
  
    <controls:CheckTree id="tree1" checkBoxStateField="@state" labelField="@label" dataProvider="{folderCollection}" width="100%" height="100%"  
                        checkBoxCloseItemsOnUnCheck="{checkBoxCloseItemsOnUnCheck.selected}"  
                        checkBoxOpenItemsOnCheck="{checkBoxOpenItemsOnCheck.selected}"  
                        checkBoxEnableState="{checkBoxEnableState.selected}"  
                        checkBoxCascadeOnCheck="{checkBoxCascadeOnCheck.selected}"  
                        checkBoxBgColor="{checkBoxBgColor.selectedColor}"  
                        checkBoxBgAlpha="{checkBoxBgAlpha.value}"  
                        checkBoxBgPadding="{checkBoxBgPadding.value}"  
                        checkBoxBgElips="{checkBoxBgElips.value}"  
                        checkBoxLeftGap="{checkBoxLeftGap.value}"  
                        checkBoxRightGap="{checkBoxRightGap.value}"  
                        itemDClickSelect="{itemDClickSelect.selected}"  
                        />  
    <controls:CheckTree id="tree2"   
                        width="100%"  
                        labelField="label"  
                        checkBoxStateField="state"  
                        dataProvider="{arrarc}"  
                        height="100%"/>  
    <controls:CheckTree id="tree3"  
                        width="100%"  
                        labelField="label"  
                        checkBoxStateField="state"  
                        dataProvider="{arrarc}"  
                        height="100%"/>  
</mx:Application>

转自:http://blog.csdn.net/cjy37/archive/2009/05/11/4166621.aspx
  • 大小: 56.1 KB
分享到:
评论
5 楼 zlbdexiaohao 2015-07-21  
怎么去掉默认的图标,
folderClosedIcon="undefined"
folderOpenIcon="undefined"
不管用
4 楼 zlbdexiaohao 2015-07-20  
看不懂看不懂
3 楼 cjy37 2010-05-15  
请楼主注明转帖的网站、作者、网址,否则请删除!!!!!
2 楼 jjxboy 2010-02-25  
楼长,能不能给个可以下载的实例啊?谢谢了!
1 楼 shijian0306 2009-12-28  
需要可下载的实例,图片打不开。。。

相关推荐

Global site tag (gtag.js) - Google Analytics