首页 > 代码库 > Flex tree加三状态的Checkbox

Flex tree加三状态的Checkbox

网上有下过其他人的实现的例子,但是样式不好改,还有就是不能初始化选中,还有三态效果那个半选中状态也是不清楚,所以自己根据Itemrender搞了一个,还凑合

效果如图:全选和半选状态,Checkbox的flex3的样式用的图片




TreeCheckboxItemRender.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:MXTreeItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
					  xmlns:s="library://ns.adobe.com/flex/spark" 
					  xmlns:mx="library://ns.adobe.com/flex/mx" initialize="mxtreeitemrenderer1_initializeHandler(event)">
	<fx:Metadata>
		[Event(name="checkBoxClick",type="CustomEvent")]
	</fx:Metadata>
	<fx:Style>
		@namespace s "library://ns.adobe.com/flex/spark";
		@namespace mx "library://ns.adobe.com/flex/mx";
		.halfSelected{
			upIcon:Embed(source='1.png');
			overIcon:Embed(source='1.png');
			downIcon:Embed(source='1.png');
			disabledIcon:Embed(source='1.png');
		}
		.selected{
			upIcon:Embed(source='4.png');
			overIcon:Embed(source='4.png');
			downIcon:Embed(source='4.png');
			disabledIcon:Embed(source='4.png');
		}
		.unSelected{
			upIcon:Embed(source='2.png');
			overIcon:Embed(source='3.png');
			downIcon:Embed(source='3.png');
			disabledIcon:Embed(source='2.png');
		}
	</fx:Style>
	<fx:Script>
		<![CDATA[
			
			import mx.controls.Tree;
			import mx.events.FlexEvent;
			[Bindable]
			[Embed(source="1.png")]
			public static var HARFSELECT_CLASS:Class;
			[Bindable]
			[Embed(source="2.png")]
			public static var UNSELECT_CLASS:Class;
			[Bindable]
			[Embed(source="3.png")]
			public static var UNSELECT_OVER_CLASS:Class;
			[Bindable]
			[Embed(source="4.png")]
			public static var SELECT_CLASS:Class;
			override protected function commitProperties():void
			{
				super.commitProperties();
				if(data != null && data.@selected != ""){
					if(data.children().length() == 0){
						if(data.@selected == "true"){
							checkBox.selected = true;
						} else{
							checkBox.selected = false;
						}
						return;
					}
					recursion(data);
				} else{
					checkBox.selected = false;
				}
			}
			
			private function recursion(dataItem:Object):void{
				//遍历所有子节点,如果子节点下还有子节点则递归
				for(var i:int = 0; i < dataItem.children().length(); i++){
					var child:XML = dataItem.children()[i];
					if(child.children().length() > 0){
						recursion(child);
					}
				}
				//查询该节点下的选中的子节点
				var selectedChild:XMLList = dataItem..node.(@pid == dataItem.@id && @selected == "true");
				var selectElement:XMLList = dataItem..node.(@selected == "true");
				//如果该节点的子节点数等于该节点下选中的子节点数,则该节点选中
				if(dataItem.children().length() == selectedChild.length()){
					checkBox.selected = true;
					dataItem.@selected = "true";
					fillCheckBox(false);
				} else{
					checkBox.selected = false;
					fillCheckBox(false);
					if(selectElement.length() > 0){
						fillCheckBox(true);
					}
				}
			}
			
			protected function checkBox_changeHandler(event:Event):void
			{
				if(data.@selected != ""){
					toggleChildrens(data);
					toggleParents(data, Tree(this.owner));
				}
				
			}
			
			private function toggleChildrens(item:Object):void{
				item.@selected = checkBox.selected;
				for(var i:int = 0; i < item.children().length(); i++){
					item.children()[i].@selected = checkBox.selected;
					toggleChildrens(item.children()[i]);
				}
			}
	
			/**
			 * // TODO : 递归设置父项目的状态
			 * @param item 项目
			 * @param tree 树对象
			 * @param state 目标状态
			 *
			 */
			private function toggleParents(item:Object, tree:Tree):void
			{
				if (item == null)
					return ;
				else
				{
				var parentItem:Object=tree.getParentItem(item);
				if(parentItem != null){
						if(item.@selected == "false"){
							parentItem.@selected = "false";
						}else{
							var flag:int = 0;
							for(var i:int = 0; i < parentItem.children().length(); i++){
								if(parentItem.children()[i].@selected == "true"){
									flag++;
								}
							}
							if(flag == parentItem.children().length()){
								parentItem.@selected = "true";
							}
						}
						toggleParents(parentItem, tree);
					}
				}
			}
			
			protected function fillCheckBox(isFill:Boolean):void
			{
				checkBox.graphics.clear();
				if (isFill)
				{
					var myRect:Rectangle=checkBox.getBounds(checkBox);
					checkBox.graphics.beginFill(0xff0000, 1)
					checkBox.graphics.drawRoundRect(myRect.x+3, myRect.y+3, checkBox.width/2, checkBox.height/2, 1, 1);
					checkBox.graphics.endFill();
					checkBox.styleName = "halfSelected";
				} else{
					if(checkBox.selected){
						checkBox.styleName = "selected";
					} else{
						checkBox.styleName = "unSelected";
					}
				}
			}
			
			protected function mxtreeitemrenderer1_initializeHandler(event:FlexEvent):void
			{
				// TODO Auto-generated method stub
				//Tree(this.owner)
			}
			
			protected function checkBox_clickHandler(event:MouseEvent):void
			{
				// TODO Auto-generated method stub
				Tree(this.owner).dispatchEvent(new CustomEvent(CustomEvent.CHECKBOX_CLICK, {"selected":checkBox.selected}));
			}
			
		]]>
	</fx:Script>
	
	
	<s:states>
		<s:State name="normal" />            
		<s:State name="hovered" />
		<s:State name="selected" />
	</s:states>
	<s:HGroup left="0" right="0" top="0" bottom="0" verticalAlign="middle">
		<s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">
			<s:fill>
				<s:SolidColor color="0xFFFFFF" />
			</s:fill>
		</s:Rect>
		<s:Group id="disclosureGroup">
			<s:BitmapImage source="{treeListData.disclosureIcon}" visible="{treeListData.hasChildren}" />
		</s:Group>
		<mx:CheckBox id="checkBox" change="checkBox_changeHandler(event)" click="checkBox_clickHandler(event)"
					 styleName="unSelected"
					 selectedDownIcon="{SELECT_CLASS}" selectedUpIcon="{SELECT_CLASS}" selectedOverIcon="{SELECT_CLASS}"/>
		<s:BitmapImage source="{treeListData.icon}" />
		<s:RichEditableText id="labelField" editable="false" text="{treeListData.label}" paddingTop="2"/>
	</s:HGroup>
</s:MXTreeItemRenderer>

主文件

<?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:components="com.pricklythistle.common.components.*">
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
		<fx:XML xmlns="" id="xmlData">
			<node id="0" pid="-1" label="厦门" openedId="-1" type="-1" cid="0" selected="false" isBranch="true">
				<node id="110" pid="0" selected="false" cid="0" isBranch="true" type="2" updateStatus="1" label="软件园演示点2" createTime="1404267128253" updateTime="1404267128253" icon="">
					<node id="362" pid="110" selected="false" cid="110" label="望海路(720P-变码率)" isBranch="false" updateStatus="1" channelValue=http://www.mamicode.com/"1" isOffLine="false" isPlaying="false" channelStatus="0" xCoordinate="0.0" yCoordinate="0.0" overdueStatus="1" createTime="1404268448260" updateTime="1404268514558" icon=""/>>
说明:在xml文件中主要的两个属性就是pid和selected属性,pid就是父ID,selected代表是否选中,如果为true初始化的时候就选中,我在Itemrender中是用这两个属性来判断这三个状态的

Flex tree加三状态的Checkbox