随笔-193  评论-715  文章-1  trackbacks-0
常常会用到带有3种状态CheckBox的树形组件,比如在权限管理中,或者是地区选择中等等,如下图:


不多说费话了,直接进入主题,看看如何实现。其实在Flex中,只用自己实现一个TreeItemRenderer就可以了,代码如下:
package com.robin {
    import flash.events.Event;
    import flash.geom.Rectangle;
    
    import mx.controls.CheckBox;
    import mx.controls.treeClasses.TreeItemRenderer;
    import mx.controls.treeClasses.TreeListData;
    import mx.events.FlexEvent;

    public class ThreeStatusCheckBoxTreeItemRenderer extends TreeItemRenderer 
{
        private static 
var _colorForThirdState:int = 0x37BEF8;
        private static 
var _selectedField:String = "selected";
        
        private 
var checkBox:CheckBox;

        public 
function ThreeStatusCheckBoxTreeItemRenderer() {
            super();
        }


        override protected 
function createChildren():void {
            super.createChildren();
            checkBox 
= new CheckBox();
            addChild(checkBox);
            checkBox.addEventListener(Event.CHANGE, changeHandler);
        }


        
/**
         * Initial data when component initialization
         *
         
*/

        override protected 
function commitProperties():void {
            super.commitProperties();
            
if (data && data.@[_selectedField] != null{
                
var s:int = int(data.@[_selectedField]);
                
var selected:Boolean = s > 0 ? true : false;
                checkBox.selected 
= selected;
            }
 else {
                checkBox.selected 
= false;
            }

        }


        
/**
         * update dataProvider when user click CheckBox
         *
         
*/

        protected 
function changeHandler(event:Event):void {
            
if (data && data.@[_selectedField] != null{
                data.@[_selectedField] 
= checkBox.selected ? "1" : "0";
            }

            
            
var listData:TreeListData = TreeListData(listData);
            
if (listData.hasChildren) {
                
var item:XML = XML(listData.item);
                handleAllChildren(item.children());
            }

            handleAllParents(listData.item.parent());
        }


        private 
function handleAllChildren(children:XMLList):void {
            
for each (var item:XML in children) {
                item.@[_selectedField] 
= checkBox.selected ? "1" : "0";
                
var children:XMLList = item.children();
                
if (children.length() > 0{
                    handleAllChildren(children);
                }

            }

        }


        private 
function handleAllParents(parent:XML):void {
            
if (parent != null{
                
var children:XMLList = parent.children();
                
var hasSelected1:Boolean = false;
                
var hasSelected2:Boolean = false;
                
var hasSelected0:Boolean = false;
                
for each (var item:XML in children) {
                    
if (int(item.@[_selectedField]) == 1{
                        hasSelected1 
= true;
                    }

                    
if (int(item.@[_selectedField]) == 2{
                        hasSelected2 
= true;
                    }

                    
if (int(item.@[_selectedField]) == 0{
                        hasSelected0 
= true;
                    }

                }

                
if (checkBox.selected == true{
                    
if (!hasSelected0 && !hasSelected2) {
                        parent.@[_selectedField] 
= "1";
                    }
 else {
                        parent.@[_selectedField] 
= "2";
                    }

                }
 else {
                    
if (!hasSelected1 && !hasSelected2) {
                        parent.@[_selectedField] 
= "0";
                    }
 else {
                        parent.@[_selectedField] 
= "2";
                    }

                }

                handleAllParents(parent.parent());
            }

        }


        
/**
         * reset itemRenderer's width
         
*/

        override protected 
function measure():void {
            super.measure();
            measuredWidth 
+= checkBox.getExplicitOrMeasuredWidth();
        }


        
/**
         * re-assign layout for tree, move lable to right
         * @param unscaledWidth
         * @param unscaledHeight
         
*/

        override protected 
function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
            
var startx:Number = data ? TreeListData(listData).indent : 0;

            
if (disclosureIcon) {
                disclosureIcon.x 
= startx;
                startx 
= disclosureIcon.x + disclosureIcon.width;
                disclosureIcon.setActualSize(disclosureIcon.width, disclosureIcon.height);
                disclosureIcon.visible 
= data ? TreeListData(listData).hasChildren : false;
            }

            
if (icon) {
                icon.x 
= startx;
                startx 
= icon.x + icon.measuredWidth;
                icon.setActualSize(icon.measuredWidth, icon.measuredHeight);
            }

            checkBox.move(startx, (unscaledHeight 
- checkBox.height) / 2);
            label.x 
= startx + checkBox.getExplicitOrMeasuredWidth();

            
var node:XML = data as XML;
            
if (int(node.@[_selectedField]) == 2{
                fillCheckBox(
true);
            }
 else {
                fillCheckBox(
false);
            }


        }

        
        
/**
         * re-draw check box for the third state
         * @param isFill
         
*/

        private 
function fillCheckBox(isFill:Boolean):void {
            checkBox.validateNow();
            checkBox.graphics.clear();
            
if (isFill) {
                
var myRect:Rectangle = checkBox.getBounds(checkBox);
                checkBox.graphics.beginFill(_colorForThirdState, 
1);
                checkBox.graphics.drawRoundRect(myRect.x, myRect.y, myRect.width, myRect.height, 
10x00FF00);
                checkBox.graphics.endFill();
            }

        }



    }

}

然后在tree组件中使用这个renderer就可以了。
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s
="library://ns.adobe.com/flex/spark" 
               xmlns:mx
="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:robin="com.robin.*">
    
<fx:Declarations>
        
<fx:XMLList id="treeData">
            
<node name = "ShangHai" type="ROOT" selected ="1">
                
<node name = "HuangPu" type="NODE" selected = "1">
                    
<node name = "A" type="NODE" selected = "1" />
                    
<node name = "B" type="NODE" selected = "1" />
                
</node>
                
<node name = "PuDong" type="NODE" selected = "1"/>
            
</node>
            
<node name = "Beijing" type="ROOT" selected = "2">
                
<node name = "HaiDian" type="NODE" selected = "0"/>
                
<node name = "ChaoYang" type="NODE" selected = "1"/>
            
</node>
        
</fx:XMLList>
    
</fx:Declarations>
    
<fx:Script>
        
<![CDATA[
            protected 
function getCurrentData_clickHandler(event:MouseEvent):void {
                currentText.text 
= String(treeData);
            }

        ]]
>
    
</fx:Script>
    
    
<mx:Tree x = "0" y = "0" width = "232" height = "285" itemRenderer = "com.robin.ThreeStatusCheckBoxTreeItemRenderer" labelField = "@name" dataProvider = "{treeData}"/>
    
<s:Button x = "43" y = "293" label = "Get Current Data" id = "getCurrentData" click = "getCurrentData_clickHandler(event)"/>
    
<s:TextArea x = "253" y = "0" width = "459" height = "285" id = "currentText"/>
</s:Application>

就是这么简单!
posted on 2010-09-15 07:58 Robin's Programming World 阅读(5926) 评论(7)  编辑  收藏 所属分类: Flex & Flash

评论:
# re: Flex中带有三种状态CheckBox的Tree的实现 2011-09-21 11:21 | 729106109
那后台用java怎么组成所需要的tree呢?谢谢了  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现 2011-10-09 12:27 | Robin's Java World
后台什么数据结构都无所谓,到前台变成XML就可以了。  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现[未登录] 2011-12-09 09:22 | neil
不行  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现 2012-01-05 14:16 | 欧巴
在Java后台拼成XML格式的字符串就可以了  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现 2013-04-27 17:21 | k-mart
三个状态,很科学,赞一个  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现 2015-07-21 10:23 | 钟凡
怎么去掉前面的小图标  回复  更多评论
  
# re: Flex中带有三种状态CheckBox的Tree的实现 2016-01-04 17:39 | bns
带有3种状态CheckBox的树形组件刚好用到
收了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: