首页 > 设计 > WEB开发 > 正文

7.12.创建一个带复选框的Tree控件

2023-08-02 23:09:27
字体:
来源:转载
供稿:网友
7.12.1.问题
你要创建一个树。它的结点一个有三个状态的CheckBox。
7.12.2.解决办法
我们从三个方面去解决这个问题:
1 创建TreeItemRenderer。这个renderer 要包含CheckBox;
2 当CheckBox 是第三种状态时,将有一个黑色的小图片覆盖在CheckBox 上方,
也就是说,这时我们看到CheckBox 的,不是空心的,也不是里边含有“勾”,而是里边含有一个实心的黑方块;
3 dataProvider 的item 中要有一个属性用于表示CheckBox 的选中状态;
7.12.3.讨论
通常我们用tree 来表现一个文件系统,而且我们经常需要同时选中多个文件,并对它们一起做某个操作,如删除,复制等。所以我们需要tree 的结点能有一种状态,表示它己经表选中了。

一个父结点的选中或取消选中操作应该同时触发它的所有子结点同时被选中或同时取消选中。如果这些子结点,有些是选中状态,有些是未选中状态,这时父结点需要有第三种状态才能更好的表现这种情况,所以我们需要有至少两个状态的CheckBox。这第三种状态表示:某个父结点的子结点有些选中,有些未选中,而它自己是选中。

我们的解决办法是自定义一个TreeItemRenderer,(就是下边的CheckTreeRenderer) 它继承自TreeItemRenderer,我们使用它实现三种状态的CheckBox。
+展开
-XML
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="init();" >

<mx:Script>
<![CDATA[
import mx.collections.*;
[Bindable]
public var folderList:XMLList = <> 
<folder state="unchecked" label="Marketing Collateral" isBranch="true">
<folder state="unchecked" isBranch="true" label="Media, PR, and Communications">
<folder state="unchecked" isBranch="false" label="Article Reprint Disclaimers"/>
<folder state="unchecked" isBranch="false" label="Articles Reprints"/>
<folder state="unchecked" isBranch="false" label="Interviews and Transcripts"/>
<folder state="unchecked" isBranch="false" label="Press Kits"/>
<folder state="unchecked" isBranch="false" label="Press Releases"/>
<folder state="unchecked" isBranch="false" label="Quick Hits"/>
<folder state="unchecked" isBranch="false" label="Rep Talking Points"/>
<folder state="unchecked" isBranch="false" label="Special Updates"/>
<folder state="unchecked" isBranch="false" label="White Papers"/>
</folder>
<folder state="unchecked" isBranch="true" label="Forms and Applications">
<folder state="unchecked" isBranch="false" label="Applications" />
<folder state="unchecked" isBranch="false" label="Forms" />
</folder>
</folder>
</>;
[Bindable]
public var folderCollection:XMLListCollection;
private function init() : void {
folderCollection = new XMLListCollection(folderList);
checkTree.dataProvider = folderCollection;
}

]]>
</mx:Script>
<mx:Tree id="checkTreeitemRenderer="oreilly.cookbook.CheckTreeRendererlabelField="@labelwidth="100%height="100%" >
</mx:Tree>
</mx:Application>

下面是CheckTreeRenderer 的代码:
+展开
-ActionScript
package oreilly.cookbook {
import mx.controls.Image;
import mx.controls.Tree;
import mx.controls.treeClasses.*;
import mx.collections.*;
import mx.controls.CheckBox;
import mx.controls.listClasses.*;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.events.FlexEvent;
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import flash.xml.*;
import mx.core.IDataRenderer;
public class CheckTreeRenderer extends TreeItemRenderer {
//Create a CheckBox and an Image:
protected var myImage:Image;
protected var myCheckBox:CheckBox;
// set image properties
private var imageWidth:Number = 6;
private var imageHeight:Number = 6;
private var inner:String = "assets/inner.png" ;
static private var STATE_SCHRODINGER:String = "schrodinger" ;
static private var STATE_CHECKED:String = "checked" ;
static private var STATE_UNCHECKED:String = "unchecked" ;
public function CheckTreeRenderer () {
super();
mouseEnabled = false ;
}
private function toggleParents (item:Object, tree:Tree, state:String):void {
if (item == null ) { return ; }
else { 
item.@state = state;
toggleParents(tree.getParentItem(item), tree,
getState (tree, tree.getParentItem(item)));
}
}
private function toggleChildren (item:Object, tree:Tree,state:String):void{
if(item == null) {return;}
else {
item.@state = state;
var treeData:ITreeDataDescriptor = tree.dataDescriptor;
if (treeData.hasChildren(item)) { 
var children:ICollectionView = treeData.getChildren (item);
var cursor:IViewCursor = children.createCursor();
while (!cursor.afterLast) {
toggleChildren(cursor.current, tree, state);
cursor.moveNext();
}
}
}
}

在每个结点被点击时,要同时设置这个结点的父结点状态,和所有子结点的状态。子结点只能被设置为CHECKED 或UNCHECKED 状态,但父结点可以设置第三种状态----SCHRODINGER,当它的子结点有CHECKED 和UNCHECKED 状态时,它就是SCHRODINGER 状态。

父结点状态的设置要根据它所有子结点的状态而定:
+展开
-ActionScript
private function getState(tree:Tree, parent:Object):String {
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.@state == STATE_CHECKED){
noChecks++;
}
else if (cursor.current.@state == STATE_UNCHECKED) {
noUnChecks++
}
else {
noCats++;
}
cursor.moveNext();
}
}
if ((noChecks > 0 && noUnChecks > 0) || (noCats > 0 && noChecks>0)) {
return STATE_SCHRODINGER;
else if (noChecks > 0) {
return STATE_CHECKED;
else { return STATE_UNCHECKED; }
}
private function imageToggleHandlder(event:MouseEvent):void {
myCheckBox.selected = !myCheckBox.selected;
checkBoxToggleHandler(event);
}

我们要为CheckBox 和Image 设置鼠标点击事件的监听:
+展开
-ActionScript
private function checkBoxToggleHandler(event:MouseEvent):void {
if (data) {
var myListData:TreeListData = TreeListData(this.listData);
var selectedNode:Object = myListData.item;
var tree:Tree = Tree(myListData.owner);
var toggle:Boolean = myCheckBox.selected;
if (toggle) {
toggleChildren(data, tree, STATE_CHECKED);
else {
toggleChildren(data, tree, STATE_UNCHECKED);
}
var parent:Object = tree.getParentItem (data);
toggleParents (parent, tree,
getState (tree, parent));
}
}

我们重写createChildren,用于创建tree 的所有子结点:
+展开
-ActionScript
override protected function createChildren():void {
super.createChildren();
myCheckBox = new CheckBox();
myCheckBox.setStyle( "verticalAlign" , "middle" );
myCheckBox.addEventListener( MouseEvent.CLICK, checkBoxToggleHandler );
addChild(myCheckBox);
myImage = new Image();
myImage.source = inner;
myImage.addEventListener( MouseEvent.CLICK, imageToggleHandler );
myImage.setStyle( "verticalAlign" , "middle" );
addChild(myImage);
}
private function setCheckState (checkBox:CheckBox, value:Object, state:String):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.@state);
if (TreeListData(super.listData).item.@type =='dimension') {
setStyle("fontStyle"'italic');
else {
if (this .parent != null ) {
var _tree:Tree = Tree(this.parent.parent);
_tree.setStyle("defaultLeafIcon" , null );
}
setStyle("fontStyle" , 'normal' );
}
}
}
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;
myCheckBox.y = 2;
super.icon.x = myCheckBox.x + myCheckBox.width +17;
super.label.x = super.icon.x + super.icon.width +3;
else{
myCheckBox.x = super.label.x;
myCheckBox.y = 2;
super.label.x = myCheckBox.x + myCheckBox.width +17;
}
if(data.@state == STATE_SCHRODINGER) {
myImage.x = myCheckBox.x + 4;
myImage.y = myCheckBox.y + 4;
myImage.width = imageWidth;
myImage.height = imageHeight;
else{
myImage.x = 0;
myImage.y = 0;
myImage.width = 0;
myImage.height = 0;
}
}
}
}
}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表