- 浏览: 151853 次
- 性别:
- 来自: 北京
最新评论
-
pandengzhegt:
好牛!正需要!谢谢了!
JPA 2.0 中的动态类型安全查询 -
yanlp:
万分的感谢。
仿google 的输入提示框 -
huangwenji6111:
可谓良师,在此拜谢!受益匪浅!
hibernate lazy -
jwx0925:
不错!mark!
hibernate对象状态 -
leftstick:
大有裨益,谢了!
hibernate lazy
原文地址:http://www.airia.cn/FLEX_Directory/working_with_tree/
Tree控件是一个枝和叶节点分层次的机构。树中没每一个条目叫做节点,节点既可以作为枝也可以作为叶。枝节点可以包含叶或枝节点,或者为空。一个叶节点就是一个树的末梢。本快速指南包含一些开发者在使用Treecontrols经常会遇到的一些挑战。
使用XMLLISTCOLLECTION 和ARRAYCOLLECTION对象的对比。
你也许想知道,在运行时从远程或本地得来的数据被动态修改的时候,应该使用XMLListCollection对象还是ArrayCollection对象作为Tree空间的数据提供者。
如果你使用的数据源提供成形的XML,并且,你想在Tree控件中操作 XML数据。你应该使用XMLListCollection对象作为数据提供者。当使用MXML标记时,如果数据源是XMLList对象,你应该把它绑定到XMLLsitCollection对象的source属性上,然后把 XMLListCollection对象绑定到Tree控件的dataProvider属性上。
当你想要动态改变对象值时,不要使用XMLList或XML对象直接绑定到Tree控件的dataProvider属性上。当数据源是RPC(远程过程调用)服务的lastResult属性,并且你想使用XML数据,确保RPC组件的resultFormat属性被设置成e4x,当你使用e4x结果格式,最总结果就是XMLList,可以绑定在XMLListCollection对象上。
这里有一个例子。为例数据被动态改变,使用ArrayCollection对象作为Tree控件的数据提供器。当使用MXML标记时,如果你期望动态的改变Arrayl,你不应该把Array对象直接绑定到Tree控件的dataProvider属性上。作为代替,你应该绑定Array到一个ArrayCollection对象的source属性上,然后再把ArrayCollection对象绑定到Tree控件的dataProvider属性上。
当数据源是RPC(远程过程调用)服务的lastResult对象,并且RPC组件的resultFormat属性被成object,你应该使用ArrayUtil.toArray()方法来确保对象是一个Array。然后绑定到ArrayCollection对象上,就像下边的例子所示:
<mx:ArrayCollection
id="employeeAC"
source= "{ArrayUtil.toArray(employeeSrv.lastResult.employees.employee)}"/>
在运行时增加和删除叶子节点
你可以在运行时为Tree控件增加或删除叶子节点。下边的例子包含的代码来实现这种改变。这个程序使用预定义的枝和叶来初始化,表现公司部门和员工。你可以向任意枝节点增加叶节点在运行时。你也可以删除预定义的叶节点和你在运行时增加的节点。
在这个例子中的XML包含两种不同的元素名字,department和employee。Tree控件的label函数,决定根据元素的类型应该显示那些文本。它使用了E4X语法来返回department的title,或者employee的name。然后,这些语法在addEmployee()和removeEmployee()中会用到。
为了增加员工到业务部门,addEmployee()方法使用E4X语法,通过title属性的值获得业务部门的节点,并把它保存到XMLList类型的变量dept中。然后,通过调用dept.appendChild()方法向操作节点添加子结点。remove方法保存当前被选择的元素到变量node中,node的类型是XML。调用node.localName()方法确定被选择的元素是否是employee节点。如果是employee节点,删除它。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
<mx:Script>
<![CDATA[ import mx.collections.XMLListCollection;
[Bindable]
private var company:XML =
<list>
<department title="Finance" code="200">
<employee name="John H"/>
<employee name="Sam K"/>
</department>
<department title="Operations" code="400">
<employee name="Bill C"/>
<employee name="Jill W"/>
</department>
<department title="Engineering" code="300">
<employee name="Erin M"/>
<employee name="Ann B"/>
</department>
</list>;
[Bindable]
private var companyData:XMLListCollection = new XMLListCollection(company.department);
private function treeLabel(item:Object):String
{
var node:XML = XML(item);
if( node.localName() == "department" )
return node.@title;
else
return node.@name;
}
private function addEmployee():void
{
var newNode:XML = <employee/>;
newNode.@name = empName.text;
var dept:XMLList =company.department.(@title == "Operations");
if( dept.length() > 0 ) {
dept[0].appendChild(newNode);
empName.text = "";
}
}
private function removeEmployee():void
{
var node:XML = XML(tree.selectedItem);
if( node == null ) return;
if( node.localName() != "employee" ) return;
var children:XMLList = XMLList(node.parent()).children();
for(var i:Number=0; i < children.length(); i++) {
if( children[i].@name == node.@name ) {
delete children[i];
}
}
}
]]>
</mx:Script>
<mx:Tree id="tree" top="72" left="50" dataProvider="{companyData}"
labelFunction="treeLabel"
height="224" width="179"/>
<mx:HBox>
<mx:Button label="Add Operations Employee" click="addEmployee()"/><mx:TextInput id="empName"/>
</mx:HBox>
<mx:Button label="Remove Selected Employee" click="removeEmployee()"/>
</mx:Application>
提示:可以通过右键flash查看官方源文件
在运行时添加一个空的枝节点
可以在运行时向Tree控件添加空的枝节点。下边的例子展示了通过数据提供器(data provider)API和数据描述器(data descriptor )API添加枝节点。通常,添加枝节点的首选途径是通过数据提供器(data provider)API。
addEmptyBranthDP()方法通过数据提供器API向使用XML数据提供器的Tree组件增加一个空节点,这个方法为新节点创建一个XML类型的变量,并且设置这个节点的isBranch属性为true来创建一个枝节点。然后这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的元素。
addEmptyBranchDP2()方法通过数据提供器API向使用对象数据提供器的Tree组件增加一个空节点,这个方法使用children属性创建一个新的对象,使用children属性能够确保isBranch()方法返回true。然后,这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的对象。
addEmptyBranchDD()方法通过数据描述器(data descripter)API。这个方法创建一个XML类型的变量,并且设置isBranch属性为true来创建一个枝节点。然后,这个方法调用Tree控件的dataDescriptor.addChildAt()方法来向Tree控件的数据描述器添加一个新的子节点。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html"> <mx:Script>
<![CDATA[
[Bindable]
private var dataX:XML =
<item label="Top">
<item label="Child One"/>
<item label="Child Two" />
</item>;
[Bindable]
private var dataObj:Object =
[{label:"Top", children:
[
{label:"Child One"}, {label: "Child Two"}
]
}];
// Adding a branch by going through the Tree control's dataProvider. This is
// the preferred method.
// Toggling the isBranch attribute to true causes DefaultDataDescriptor.isBranch()
// to return true and the Tree treats the node as a branch.
private function addEmptyBranchDP():void
{
var newNode:XML = <item label='Middle' isBranch="true"></item>;
xmlBound2Tree.dataProvider.addItemAt(newNode, 1);
}
// For an object graph, the key point is that the children property needs to be defined,
// even if it is empty.
// This causes isBranch() to return true and the Tree treats the new node as a branch.
private function addEmptyBranchDP2():void
{
var newObj:Object = {label:"Middle", children:[]};
objGraphBound2Tree.dataProvider.addItemAt(newObj, 1);
}
// Adding a branch by going through the Tree control's dataDescriptor.
private function addEmptyBranchDD():void
{
var newNode:XML = <item label='Child 4' isBranch="true"></item>;
xmlBound2Tree.dataDescriptor.addChildAt(dataX, newNode, 2, dataX);
}
]]>
</mx:Script>
<mx:Label text="Tree with XML data"/>
<mx:Tree id="xmlBound2Tree" dataProvider="{dataX}" labelField="@label" showRoot="true" width="200"/>
<mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP();"/>
<mx:Button label="Add Empty Branch through the dataDescriptor" click="addEmptyBranchDD();"/>
<mx:Spacer height="10"/>
<mx:Label text="Tree with object data"/>
<mx:Tree id="objGraphBound2Tree" dataProvider="{dataObj}" width="200"/>
<mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP2();"/>
</mx:Application>
结果
打开树到指定的节点
默认的,Tree控件在初始化后是收缩的,你也许不确定如何初始化控件时展开数,并且选定指定的节点。下边的例子,展示了如何实现它。在这个程序中,initTree()方法,在Tree控件被创建后调用。这个方法展开Tree控件的根节点,并且设置selectedIndex属性为指定节点的索引号。
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html"> <mx:Script>
<![CDATA[
import flash.events.*;
import mx.events.*;
import mx.controls.*;
private function initTree():void {
XMLTree1.expandItem(MailBox.getItemAt(0), true);
XMLTree1.selectedIndex = 2;
}
]]>
</mx:Script>
<mx:Tree id="XMLTree1" width="150" height="170"
labelField="@label" creationComplete="initTree();">
<mx:XMLListCollection id="MailBox">
<mx:XMLList>
<node label="Mail" data="100">
<node label="Inbox" data="70"/>
<node label="Personal Folder" data="10">
<node label="Business" data="2"/>
<node label="Demo" data="3"/>
<node label="Saved Mail" data="5" />
</node>
<node label="Sent" data="15"/>
<node label="Trash" data="5"/>
</node>
</mx:XMLList>
</mx:XMLListCollection>
</mx:Tree>
</mx:Application>
结果
读取多节点名XML文档
你可以从具有多个节点名字的XML文档中组装Tree 控件。下边的例子实现了这个功能。Tree控件的数据提供者是一个XMLListCollection,它组装自一个包含folder和Pfolder元素的XMLList。Tree控件的labelField属性被设置为label属性,不管元素叫什么名字,这个属性对XMLList中的所有属性都是公共的。
例子
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
<mx:Tree id="tree1" dataProvider="{MailBox}" labelField="@label" showRoot="true" width="160"/>
<mx:XMLListCollection id="MailBox" source="{Folders}"/>
<mx:XMLList id="Folders">
<folder label="Mail">
<folder label="INBOX"/>
<folder label="Personal Folder">
<Pfolder label="Business" />
<Pfolder label="Demo" />
<Pfolder label="Saved Mail" />
</folder>
<folder label="Sent" />
<folder label="Trash" />
</folder>
</mx:XMLList>
</mx:Application>
结果
当数据提供器更新时保持Tree控件打开
默认地,当数据提供器更新数据时Tree控件收缩。下边的例子展示了当数据提供器更新时保持Tree控件打开的方法。
在这个应用程序中,当一个用户单击Button控件时changeProvider()方法更新数据提供器。通常,这会导致Tree控件收缩。然而,Tree控件的渲染事件处理器,renderTree()方法,放置收缩的发生。当changerProvider()方法被调用,当前状态是打开的元素被保存到对象open变量中。当数据被刷新时,被命名为refreshData的Boolean类型的变量被置为true。renderTree()方法调用Tree控件的invalidateList()方法来刷新树的行。然后置refreshDate属性为false,并且重置Tree控件的打开元素属性为open对象变量,这个变量在刷新前就包含了状态是打开的元素。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="initTree()" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
[Bindable]
public var open:Object = new Object();
[Bindable]
public var refreshData:Boolean = false;
[Bindable]
public var switchObj:Object = new Object();
[Bindable]
public var firstObj:Object = new Object();
[Bindable]
public var firstObj1:Object = new Object();
[Bindable]
public var firstObj2:Object = new Object();
[Bindable]
public var provider:String = "firstObj";
private function initTree():void
{
firstObj = new Object();
firstObj.label = "Foods";
firstObj.children = new Array();
firstObj1.label = "Fruits";
firstObj1.children = new Array();
firstObj2.label = "Oranges";
firstObj1.children[0] = firstObj2;
firstObj.children[0] = firstObj1;
switchObj = firstObj;
}
public function changeProvider():void
{
open = SampleTree.openItems;
refreshData = true;
if (provider == "firstObj")
{
provider = "switchObj";
SampleTree.dataProvider = switchObj;
}
else
{
provider = "firstObj";
SampleTree.dataProvider = firstObj;
}
}
public function renderTree():void{
if(refreshData){
// Refresh all rows on next update.
SampleTree.invalidateList();
refreshData = false;
SampleTree.openItems = open;
// Validate and update the properties and layout
// of this object and redraw it, if necessary.
SampleTree.validateNow();
}
}
]]>
</mx:Script>
<mx:Tree id="SampleTree" render="renderTree()" width="250" dataProvider="{firstObj}" labelField="label" />
<mx:Button label="Change Data Provider" click="changeProvider()"/>
</mx:Application>
结果
项和一个树控件拖放
拖拽元素到Tree控件,和从Tree控件拖拽出元素创建一个应用程序,实现拖拽元素从Tree控件中,或到Tree控件是令人畏惧的,很明显,因为需要大量的事件处理逻辑。本节提供2个例子,来示范实现这2种功能的技术。从Tree控件中拖拽出元素下边的例子展示如何从Tree控件中拖拽元素到DataGrid控件中。Tree控件的数据提供器是XML对象。通过拖拽事件处理方法前的注释可以使你读懂整个应用程序。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.Label;
import mx.controls.List;
import mx.collections.ArrayCollection;
import mx.core.DragSource;
import mx.controls.Tree;
import mx.controls.DataGrid;
import mx.controls.listClasses.ListBase;
import mx.events.DragEvent;
import mx.containers.Canvas;
import mx.managers.DragManager;
import mx.core.UIComponent;
[Bindable]
private var dataGridProvider:ArrayCollection = new ArrayCollection();
/**
* Handles the dragEnter event on the DataGrid control.
* If the dragInitiator is the Tree control, then only nodes of type "restaurant"
* are permitted to be dropped.
* Here you can see that by examining the dragSource you can determine if
* the control should accept the drop. The DataGrid control would not
* know how to treat a branch+children from the Tree control, so only leaf (restaurant)
* nodes are accepted.
*/
private function onDragEnter( event:DragEvent ) : void
{
if( event.dragInitiator is Tree ) {
var ds:DragSource = event.dragSource;
if( !ds.hasFormat("treeItems") ) return; // no useful data
var items:Array = ds.dataForFormat("treeItems") as Array;
for(var i:Number=0; i < items.length; i++) {
var item:XML = XML(items[i]);
if( item.@type != "restaurant" ) return; // not what we want
}
}
// If the Tree control passes or the dragInitiator is not a Tree control,
// accept the drop.
DragManager.acceptDragDrop(UIComponent(event.currentTarget));
}
/**
* Handles the dragOver event on the DataGrid control.
* If the dragInitiator is the Tree control, only copy is allowed. Otherwise, a move
* or link can take place from the List control.
*/
private function onDragOver( event:DragEvent ) : void
{
if( event.dragInitiator is Tree ) {
DragManager.showFeedback(DragManager.COPY);
} else {
if (event.ctrlKey)
DragManager.showFeedback(DragManager.COPY);
else if (event.shiftKey)
DragManager.showFeedback(DragManager.LINK);
else {
DragManager.showFeedback(DragManager.MOVE);
}
}
}
/**
* Handles the dragExit event on the drop target and just hides the
* the drop feedback.
*/
private function onDragExit( event:DragEvent ) : void
{
var dropTarget:ListBase=ListBase(event.currentTarget);
dropTarget.hideDropFeedback(event);
}
/**
* Handles the dragDrop event on the DataGrid when the
* drag proxy is released.
*/
private function onGridDragDrop( event:DragEvent ) : void
{
var ds:DragSource = event.dragSource;
var dropTarget:DataGrid = DataGrid(event.currentTarget);
var arr:Array;
if( ds.hasFormat("items") ) {
arr = ds.dataForFormat("items") as Array;
} else if( ds.hasFormat("treeItems") ) {
arr = ds.dataForFormat("treeItems") as Array;
}
for(var i:Number=0; i < arr.length; i++) {
var node:XML = XML(arr[i]);
var item:Object = new Object();
item.label = node.@label;
item.type = node.@type;
dataGridProvider.addItem(item);
}
onDragExit(event);
}
/**
* Intercepts the dragComplete event on the Tree control
* and prevents the default behavior from happening. This is necessary
* if the item being dragged from the Tree control is dropped on a non-Tree
* object, such as the DataGrid.
*/
private function onTreeDragComplete(event:DragEvent):void {
event.preventDefault();
}
/**
* Selects all of the items in the List if Ctrl+A is picked when the List control
* has focus.
*/
private function selectAllMaybe( event:KeyboardEvent ) : void
{
if( event.ctrlKey && event.keyCode == 65 ) {
var l:List = List(event.currentTarget);
var allItems:Array = new Array(l.dataProvider.length);
for(var i:Number=0; i < allItems.length; i++) {
allItems[i] = i;
}
l.selectedIndices = allItems;
}
}
]]>
</mx:Script>
<mx:XML id="treeData" xmlns="">
<root>
<node label="Massachusetts" type="state" data="MA">
<node label="Boston" type="city" >
<node label="Smoke House Grill" type="restaurant" />
<node label="Equator" type="restaurant" />
<node label="Aquataine" type="restaurant" />
<node label="Grill 23" type="restaurant" />
</node>
<node label="Provincetown" type="city" >
<node label="Lobster Pot" type="restaurant" />
<node label="The Mews" type="restaurant" />
</node>
</node>
<node label="California" type="state" data="CA">
<node label="San Francisco" type="city" >
<node label="Frog Lane" type="restaurant" />
</node>
</node>
</root>
</mx:XML>
<mx:Label x="34" y="40" text="Drag items from this Tree"/>
<mx:Label x="34" y="55" text="(items are copied)"/>
<mx:Tree x="34" y="81" width="181" height="189"
dataProvider="{treeData.node}"
labelField="@label"
dropEnabled="false"
dragEnabled="true"
dragComplete="onTreeDragComplete(event)"
dragMoveEnabled="false"
/>
<mx:Label x="291" y="55" text="Drop items from Tree here"/>
<mx:DataGrid x="291" y="81" height="189"
dragEnabled="true"
dataProvider="{dataGridProvider}"
dragEnter="onDragEnter(event)"
dragOver="onDragOver(event)"
dragDrop="onGridDragDrop(event)"
dragExit="onDragExit(event)">
<mx:columns>
<mx:DataGridColumn headerText="Label" dataField="label"/>
<mx:DataGridColumn headerText="Type" dataField="type"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
树控件拖放
下面的示例演示如何将项从列表控件拖到树控件。 树数据提供程序是XML对象。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.core.UIComponent;
import mx.controls.Tree;
/**
* Called as soon as the dragProxy enters the target. You can add logic
* to determine if the target will accept the drop based on the
* dragInitiator, the data available in the dragSource.
* Here the drop is blindly accepted.
*/
private function onDragEnter( event:DragEvent ) : void
{
DragManager.acceptDragDrop(UIComponent(event.currentTarget));
}
/**
* Called while the dragProxy is over the drop target. You can
* use this function to determine the type of feedback to show.
* Since the List is set to allow MOVE (the item is deleted
* once dropped), different feedback possibilities are given.
*
* Also, for this application, the Tree control node the dragProxy is
* over is selected. As the dragProxy moves, the Tree control's
* selection changes.
*
* For a bit more complication, the drop is being allowed
* only over nodes whose type is NOT 'state'.
* The feedback is removed.
*/
private function onDragOver( event:DragEvent ) : void
{
var dropTarget:Tree = Tree(event.currentTarget);
var r:int = dropTarget.calculateDropIndex(event);
tree.selectedIndex = r;
var node:XML = tree.selectedItem as XML;
if( node.@type == "state" ) {
DragManager.showFeedback(DragManager.NONE);
return;
}
if (event.ctrlKey)
DragManager.showFeedback(DragManager.COPY);
else if (event.shiftKey)
DragManager.showFeedback(DragManager.LINK);
else {
DragManager.showFeedback(DragManager.MOVE);
}
}
/**
* Called when the dragProxy is released
* over the drop target. The information in the dragSource
* is extracted and processed.
*
* The target node is determined and
* all of the data selected (the List has allowMultipleSection
* set) is added.
*/
private function onDragDrop( event:DragEvent ) : void
{
var ds:DragSource = event.dragSource;
var dropTarget:Tree = Tree(event.currentTarget);
var items:Array = ds.dataForFormat("items") as Array;
var r:int = tree.calculateDropIndex(event);
tree.selectedIndex = r;
var node:XML = tree.selectedItem as XML;
var p:*;
// if the selected node has children (it is type==city),
// then add the items at the beginning
if( tree.dataDescriptor.hasChildren(node) ) {
p = node;
r = 0;
} else {
p = node.parent();
}
for(var i:Number=0; i < items.length; i++) {
var insert:XML = <node />;
insert.@label = items[i];
insert.@type = "restaurant";
tree.dataDescriptor.addChildAt(p, insert, r+i);
}
}
/**
* Called when the drag operation completes, whether
* successfully or not. The tree is cleared of its
* selection.
*/
private function onDragComplete( event:DragEvent ) : void
{
tree.selectedIndex = -1;
}
]]>
</mx:Script>
<mx:XML id="treeData" xmlns="">
<root>
<node label="Massachusetts" type="state" data="MA">
<node label="Boston" type="city" >
<node label="Smoke House Grill" type="restaurant" />
<node label="Equator" type="restaurant" />
<node label="Aquataine" type="restaurant" />
<node label="Grill 23" type="restaurant" />
</node>
<node label="Provincetown" type="city" >
<node label="Lobster Pot" type="restaurant" />
<node label="The Mews" type="restaurant" />
</node>
</node>
<node label="California" type="state" data="CA">
<node label="San Francisco" type="city" >
<node label="Frog Lane" type="restaurant" />
</node>
</node>
</root>
</mx:XML>
<mx:Array id="listData">
<mx:String>Johnny Rocket's</mx:String>
<mx:String>Jet Pizza</mx:String>
<mx:String>Steve's Greek</mx:String>
<mx:String>Sonsie</mx:String>
<mx:String>The Border Cafe</mx:String>
</mx:Array>
<mx:Panel x="48" y="125" width="447" height="351" layout="absolute" title="Drag onto Tree">
<mx:Tree width="186" left="10" top="10" bottom="10" id="tree"
labelField="@label"
dataProvider="{treeData.node}"
dropEnabled="false"
dragMoveEnabled="false"
dragEnter="onDragEnter(event)"
dragOver="onDragOver(event)"
dragDrop="onDragDrop(event)">
</mx:Tree>
<mx:List width="188" height="206" right="10" bottom="10" id="list"
allowMultipleSelection="true"
dataProvider="{listData}"
dragEnabled="true"
dragMoveEnabled="true"
dragComplete="onDragComplete(event)">
</mx:List>
<mx:Text x="229" y="10" text="Drag from the list below to the tree" width="188" height="39"/>
<mx:Label x="229" y="69" text="restaurants"/>
</mx:Panel>
</mx:Application>
结果
Tree控件是一个枝和叶节点分层次的机构。树中没每一个条目叫做节点,节点既可以作为枝也可以作为叶。枝节点可以包含叶或枝节点,或者为空。一个叶节点就是一个树的末梢。本快速指南包含一些开发者在使用Treecontrols经常会遇到的一些挑战。
使用XMLLISTCOLLECTION 和ARRAYCOLLECTION对象的对比。
你也许想知道,在运行时从远程或本地得来的数据被动态修改的时候,应该使用XMLListCollection对象还是ArrayCollection对象作为Tree空间的数据提供者。
如果你使用的数据源提供成形的XML,并且,你想在Tree控件中操作 XML数据。你应该使用XMLListCollection对象作为数据提供者。当使用MXML标记时,如果数据源是XMLList对象,你应该把它绑定到XMLLsitCollection对象的source属性上,然后把 XMLListCollection对象绑定到Tree控件的dataProvider属性上。
当你想要动态改变对象值时,不要使用XMLList或XML对象直接绑定到Tree控件的dataProvider属性上。当数据源是RPC(远程过程调用)服务的lastResult属性,并且你想使用XML数据,确保RPC组件的resultFormat属性被设置成e4x,当你使用e4x结果格式,最总结果就是XMLList,可以绑定在XMLListCollection对象上。
这里有一个例子。为例数据被动态改变,使用ArrayCollection对象作为Tree控件的数据提供器。当使用MXML标记时,如果你期望动态的改变Arrayl,你不应该把Array对象直接绑定到Tree控件的dataProvider属性上。作为代替,你应该绑定Array到一个ArrayCollection对象的source属性上,然后再把ArrayCollection对象绑定到Tree控件的dataProvider属性上。
当数据源是RPC(远程过程调用)服务的lastResult对象,并且RPC组件的resultFormat属性被成object,你应该使用ArrayUtil.toArray()方法来确保对象是一个Array。然后绑定到ArrayCollection对象上,就像下边的例子所示:
<mx:ArrayCollection
id="employeeAC"
source= "{ArrayUtil.toArray(employeeSrv.lastResult.employees.employee)}"/>
在运行时增加和删除叶子节点
你可以在运行时为Tree控件增加或删除叶子节点。下边的例子包含的代码来实现这种改变。这个程序使用预定义的枝和叶来初始化,表现公司部门和员工。你可以向任意枝节点增加叶节点在运行时。你也可以删除预定义的叶节点和你在运行时增加的节点。
在这个例子中的XML包含两种不同的元素名字,department和employee。Tree控件的label函数,决定根据元素的类型应该显示那些文本。它使用了E4X语法来返回department的title,或者employee的name。然后,这些语法在addEmployee()和removeEmployee()中会用到。
为了增加员工到业务部门,addEmployee()方法使用E4X语法,通过title属性的值获得业务部门的节点,并把它保存到XMLList类型的变量dept中。然后,通过调用dept.appendChild()方法向操作节点添加子结点。remove方法保存当前被选择的元素到变量node中,node的类型是XML。调用node.localName()方法确定被选择的元素是否是employee节点。如果是employee节点,删除它。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
<mx:Script>
<![CDATA[ import mx.collections.XMLListCollection;
[Bindable]
private var company:XML =
<list>
<department title="Finance" code="200">
<employee name="John H"/>
<employee name="Sam K"/>
</department>
<department title="Operations" code="400">
<employee name="Bill C"/>
<employee name="Jill W"/>
</department>
<department title="Engineering" code="300">
<employee name="Erin M"/>
<employee name="Ann B"/>
</department>
</list>;
[Bindable]
private var companyData:XMLListCollection = new XMLListCollection(company.department);
private function treeLabel(item:Object):String
{
var node:XML = XML(item);
if( node.localName() == "department" )
return node.@title;
else
return node.@name;
}
private function addEmployee():void
{
var newNode:XML = <employee/>;
newNode.@name = empName.text;
var dept:XMLList =company.department.(@title == "Operations");
if( dept.length() > 0 ) {
dept[0].appendChild(newNode);
empName.text = "";
}
}
private function removeEmployee():void
{
var node:XML = XML(tree.selectedItem);
if( node == null ) return;
if( node.localName() != "employee" ) return;
var children:XMLList = XMLList(node.parent()).children();
for(var i:Number=0; i < children.length(); i++) {
if( children[i].@name == node.@name ) {
delete children[i];
}
}
}
]]>
</mx:Script>
<mx:Tree id="tree" top="72" left="50" dataProvider="{companyData}"
labelFunction="treeLabel"
height="224" width="179"/>
<mx:HBox>
<mx:Button label="Add Operations Employee" click="addEmployee()"/><mx:TextInput id="empName"/>
</mx:HBox>
<mx:Button label="Remove Selected Employee" click="removeEmployee()"/>
</mx:Application>
提示:可以通过右键flash查看官方源文件
在运行时添加一个空的枝节点
可以在运行时向Tree控件添加空的枝节点。下边的例子展示了通过数据提供器(data provider)API和数据描述器(data descriptor )API添加枝节点。通常,添加枝节点的首选途径是通过数据提供器(data provider)API。
addEmptyBranthDP()方法通过数据提供器API向使用XML数据提供器的Tree组件增加一个空节点,这个方法为新节点创建一个XML类型的变量,并且设置这个节点的isBranch属性为true来创建一个枝节点。然后这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的元素。
addEmptyBranchDP2()方法通过数据提供器API向使用对象数据提供器的Tree组件增加一个空节点,这个方法使用children属性创建一个新的对象,使用children属性能够确保isBranch()方法返回true。然后,这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的对象。
addEmptyBranchDD()方法通过数据描述器(data descripter)API。这个方法创建一个XML类型的变量,并且设置isBranch属性为true来创建一个枝节点。然后,这个方法调用Tree控件的dataDescriptor.addChildAt()方法来向Tree控件的数据描述器添加一个新的子节点。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html"> <mx:Script>
<![CDATA[
[Bindable]
private var dataX:XML =
<item label="Top">
<item label="Child One"/>
<item label="Child Two" />
</item>;
[Bindable]
private var dataObj:Object =
[{label:"Top", children:
[
{label:"Child One"}, {label: "Child Two"}
]
}];
// Adding a branch by going through the Tree control's dataProvider. This is
// the preferred method.
// Toggling the isBranch attribute to true causes DefaultDataDescriptor.isBranch()
// to return true and the Tree treats the node as a branch.
private function addEmptyBranchDP():void
{
var newNode:XML = <item label='Middle' isBranch="true"></item>;
xmlBound2Tree.dataProvider.addItemAt(newNode, 1);
}
// For an object graph, the key point is that the children property needs to be defined,
// even if it is empty.
// This causes isBranch() to return true and the Tree treats the new node as a branch.
private function addEmptyBranchDP2():void
{
var newObj:Object = {label:"Middle", children:[]};
objGraphBound2Tree.dataProvider.addItemAt(newObj, 1);
}
// Adding a branch by going through the Tree control's dataDescriptor.
private function addEmptyBranchDD():void
{
var newNode:XML = <item label='Child 4' isBranch="true"></item>;
xmlBound2Tree.dataDescriptor.addChildAt(dataX, newNode, 2, dataX);
}
]]>
</mx:Script>
<mx:Label text="Tree with XML data"/>
<mx:Tree id="xmlBound2Tree" dataProvider="{dataX}" labelField="@label" showRoot="true" width="200"/>
<mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP();"/>
<mx:Button label="Add Empty Branch through the dataDescriptor" click="addEmptyBranchDD();"/>
<mx:Spacer height="10"/>
<mx:Label text="Tree with object data"/>
<mx:Tree id="objGraphBound2Tree" dataProvider="{dataObj}" width="200"/>
<mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP2();"/>
</mx:Application>
结果
打开树到指定的节点
默认的,Tree控件在初始化后是收缩的,你也许不确定如何初始化控件时展开数,并且选定指定的节点。下边的例子,展示了如何实现它。在这个程序中,initTree()方法,在Tree控件被创建后调用。这个方法展开Tree控件的根节点,并且设置selectedIndex属性为指定节点的索引号。
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html"> <mx:Script>
<![CDATA[
import flash.events.*;
import mx.events.*;
import mx.controls.*;
private function initTree():void {
XMLTree1.expandItem(MailBox.getItemAt(0), true);
XMLTree1.selectedIndex = 2;
}
]]>
</mx:Script>
<mx:Tree id="XMLTree1" width="150" height="170"
labelField="@label" creationComplete="initTree();">
<mx:XMLListCollection id="MailBox">
<mx:XMLList>
<node label="Mail" data="100">
<node label="Inbox" data="70"/>
<node label="Personal Folder" data="10">
<node label="Business" data="2"/>
<node label="Demo" data="3"/>
<node label="Saved Mail" data="5" />
</node>
<node label="Sent" data="15"/>
<node label="Trash" data="5"/>
</node>
</mx:XMLList>
</mx:XMLListCollection>
</mx:Tree>
</mx:Application>
结果
读取多节点名XML文档
你可以从具有多个节点名字的XML文档中组装Tree 控件。下边的例子实现了这个功能。Tree控件的数据提供者是一个XMLListCollection,它组装自一个包含folder和Pfolder元素的XMLList。Tree控件的labelField属性被设置为label属性,不管元素叫什么名字,这个属性对XMLList中的所有属性都是公共的。
例子
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
<mx:Tree id="tree1" dataProvider="{MailBox}" labelField="@label" showRoot="true" width="160"/>
<mx:XMLListCollection id="MailBox" source="{Folders}"/>
<mx:XMLList id="Folders">
<folder label="Mail">
<folder label="INBOX"/>
<folder label="Personal Folder">
<Pfolder label="Business" />
<Pfolder label="Demo" />
<Pfolder label="Saved Mail" />
</folder>
<folder label="Sent" />
<folder label="Trash" />
</folder>
</mx:XMLList>
</mx:Application>
结果
当数据提供器更新时保持Tree控件打开
默认地,当数据提供器更新数据时Tree控件收缩。下边的例子展示了当数据提供器更新时保持Tree控件打开的方法。
在这个应用程序中,当一个用户单击Button控件时changeProvider()方法更新数据提供器。通常,这会导致Tree控件收缩。然而,Tree控件的渲染事件处理器,renderTree()方法,放置收缩的发生。当changerProvider()方法被调用,当前状态是打开的元素被保存到对象open变量中。当数据被刷新时,被命名为refreshData的Boolean类型的变量被置为true。renderTree()方法调用Tree控件的invalidateList()方法来刷新树的行。然后置refreshDate属性为false,并且重置Tree控件的打开元素属性为open对象变量,这个变量在刷新前就包含了状态是打开的元素。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="initTree()" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
[Bindable]
public var open:Object = new Object();
[Bindable]
public var refreshData:Boolean = false;
[Bindable]
public var switchObj:Object = new Object();
[Bindable]
public var firstObj:Object = new Object();
[Bindable]
public var firstObj1:Object = new Object();
[Bindable]
public var firstObj2:Object = new Object();
[Bindable]
public var provider:String = "firstObj";
private function initTree():void
{
firstObj = new Object();
firstObj.label = "Foods";
firstObj.children = new Array();
firstObj1.label = "Fruits";
firstObj1.children = new Array();
firstObj2.label = "Oranges";
firstObj1.children[0] = firstObj2;
firstObj.children[0] = firstObj1;
switchObj = firstObj;
}
public function changeProvider():void
{
open = SampleTree.openItems;
refreshData = true;
if (provider == "firstObj")
{
provider = "switchObj";
SampleTree.dataProvider = switchObj;
}
else
{
provider = "firstObj";
SampleTree.dataProvider = firstObj;
}
}
public function renderTree():void{
if(refreshData){
// Refresh all rows on next update.
SampleTree.invalidateList();
refreshData = false;
SampleTree.openItems = open;
// Validate and update the properties and layout
// of this object and redraw it, if necessary.
SampleTree.validateNow();
}
}
]]>
</mx:Script>
<mx:Tree id="SampleTree" render="renderTree()" width="250" dataProvider="{firstObj}" labelField="label" />
<mx:Button label="Change Data Provider" click="changeProvider()"/>
</mx:Application>
结果
项和一个树控件拖放
拖拽元素到Tree控件,和从Tree控件拖拽出元素创建一个应用程序,实现拖拽元素从Tree控件中,或到Tree控件是令人畏惧的,很明显,因为需要大量的事件处理逻辑。本节提供2个例子,来示范实现这2种功能的技术。从Tree控件中拖拽出元素下边的例子展示如何从Tree控件中拖拽元素到DataGrid控件中。Tree控件的数据提供器是XML对象。通过拖拽事件处理方法前的注释可以使你读懂整个应用程序。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.Label;
import mx.controls.List;
import mx.collections.ArrayCollection;
import mx.core.DragSource;
import mx.controls.Tree;
import mx.controls.DataGrid;
import mx.controls.listClasses.ListBase;
import mx.events.DragEvent;
import mx.containers.Canvas;
import mx.managers.DragManager;
import mx.core.UIComponent;
[Bindable]
private var dataGridProvider:ArrayCollection = new ArrayCollection();
/**
* Handles the dragEnter event on the DataGrid control.
* If the dragInitiator is the Tree control, then only nodes of type "restaurant"
* are permitted to be dropped.
* Here you can see that by examining the dragSource you can determine if
* the control should accept the drop. The DataGrid control would not
* know how to treat a branch+children from the Tree control, so only leaf (restaurant)
* nodes are accepted.
*/
private function onDragEnter( event:DragEvent ) : void
{
if( event.dragInitiator is Tree ) {
var ds:DragSource = event.dragSource;
if( !ds.hasFormat("treeItems") ) return; // no useful data
var items:Array = ds.dataForFormat("treeItems") as Array;
for(var i:Number=0; i < items.length; i++) {
var item:XML = XML(items[i]);
if( item.@type != "restaurant" ) return; // not what we want
}
}
// If the Tree control passes or the dragInitiator is not a Tree control,
// accept the drop.
DragManager.acceptDragDrop(UIComponent(event.currentTarget));
}
/**
* Handles the dragOver event on the DataGrid control.
* If the dragInitiator is the Tree control, only copy is allowed. Otherwise, a move
* or link can take place from the List control.
*/
private function onDragOver( event:DragEvent ) : void
{
if( event.dragInitiator is Tree ) {
DragManager.showFeedback(DragManager.COPY);
} else {
if (event.ctrlKey)
DragManager.showFeedback(DragManager.COPY);
else if (event.shiftKey)
DragManager.showFeedback(DragManager.LINK);
else {
DragManager.showFeedback(DragManager.MOVE);
}
}
}
/**
* Handles the dragExit event on the drop target and just hides the
* the drop feedback.
*/
private function onDragExit( event:DragEvent ) : void
{
var dropTarget:ListBase=ListBase(event.currentTarget);
dropTarget.hideDropFeedback(event);
}
/**
* Handles the dragDrop event on the DataGrid when the
* drag proxy is released.
*/
private function onGridDragDrop( event:DragEvent ) : void
{
var ds:DragSource = event.dragSource;
var dropTarget:DataGrid = DataGrid(event.currentTarget);
var arr:Array;
if( ds.hasFormat("items") ) {
arr = ds.dataForFormat("items") as Array;
} else if( ds.hasFormat("treeItems") ) {
arr = ds.dataForFormat("treeItems") as Array;
}
for(var i:Number=0; i < arr.length; i++) {
var node:XML = XML(arr[i]);
var item:Object = new Object();
item.label = node.@label;
item.type = node.@type;
dataGridProvider.addItem(item);
}
onDragExit(event);
}
/**
* Intercepts the dragComplete event on the Tree control
* and prevents the default behavior from happening. This is necessary
* if the item being dragged from the Tree control is dropped on a non-Tree
* object, such as the DataGrid.
*/
private function onTreeDragComplete(event:DragEvent):void {
event.preventDefault();
}
/**
* Selects all of the items in the List if Ctrl+A is picked when the List control
* has focus.
*/
private function selectAllMaybe( event:KeyboardEvent ) : void
{
if( event.ctrlKey && event.keyCode == 65 ) {
var l:List = List(event.currentTarget);
var allItems:Array = new Array(l.dataProvider.length);
for(var i:Number=0; i < allItems.length; i++) {
allItems[i] = i;
}
l.selectedIndices = allItems;
}
}
]]>
</mx:Script>
<mx:XML id="treeData" xmlns="">
<root>
<node label="Massachusetts" type="state" data="MA">
<node label="Boston" type="city" >
<node label="Smoke House Grill" type="restaurant" />
<node label="Equator" type="restaurant" />
<node label="Aquataine" type="restaurant" />
<node label="Grill 23" type="restaurant" />
</node>
<node label="Provincetown" type="city" >
<node label="Lobster Pot" type="restaurant" />
<node label="The Mews" type="restaurant" />
</node>
</node>
<node label="California" type="state" data="CA">
<node label="San Francisco" type="city" >
<node label="Frog Lane" type="restaurant" />
</node>
</node>
</root>
</mx:XML>
<mx:Label x="34" y="40" text="Drag items from this Tree"/>
<mx:Label x="34" y="55" text="(items are copied)"/>
<mx:Tree x="34" y="81" width="181" height="189"
dataProvider="{treeData.node}"
labelField="@label"
dropEnabled="false"
dragEnabled="true"
dragComplete="onTreeDragComplete(event)"
dragMoveEnabled="false"
/>
<mx:Label x="291" y="55" text="Drop items from Tree here"/>
<mx:DataGrid x="291" y="81" height="189"
dragEnabled="true"
dataProvider="{dataGridProvider}"
dragEnter="onDragEnter(event)"
dragOver="onDragOver(event)"
dragDrop="onGridDragDrop(event)"
dragExit="onDragExit(event)">
<mx:columns>
<mx:DataGridColumn headerText="Label" dataField="label"/>
<mx:DataGridColumn headerText="Type" dataField="type"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
树控件拖放
下面的示例演示如何将项从列表控件拖到树控件。 树数据提供程序是XML对象。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.core.UIComponent;
import mx.controls.Tree;
/**
* Called as soon as the dragProxy enters the target. You can add logic
* to determine if the target will accept the drop based on the
* dragInitiator, the data available in the dragSource.
* Here the drop is blindly accepted.
*/
private function onDragEnter( event:DragEvent ) : void
{
DragManager.acceptDragDrop(UIComponent(event.currentTarget));
}
/**
* Called while the dragProxy is over the drop target. You can
* use this function to determine the type of feedback to show.
* Since the List is set to allow MOVE (the item is deleted
* once dropped), different feedback possibilities are given.
*
* Also, for this application, the Tree control node the dragProxy is
* over is selected. As the dragProxy moves, the Tree control's
* selection changes.
*
* For a bit more complication, the drop is being allowed
* only over nodes whose type is NOT 'state'.
* The feedback is removed.
*/
private function onDragOver( event:DragEvent ) : void
{
var dropTarget:Tree = Tree(event.currentTarget);
var r:int = dropTarget.calculateDropIndex(event);
tree.selectedIndex = r;
var node:XML = tree.selectedItem as XML;
if( node.@type == "state" ) {
DragManager.showFeedback(DragManager.NONE);
return;
}
if (event.ctrlKey)
DragManager.showFeedback(DragManager.COPY);
else if (event.shiftKey)
DragManager.showFeedback(DragManager.LINK);
else {
DragManager.showFeedback(DragManager.MOVE);
}
}
/**
* Called when the dragProxy is released
* over the drop target. The information in the dragSource
* is extracted and processed.
*
* The target node is determined and
* all of the data selected (the List has allowMultipleSection
* set) is added.
*/
private function onDragDrop( event:DragEvent ) : void
{
var ds:DragSource = event.dragSource;
var dropTarget:Tree = Tree(event.currentTarget);
var items:Array = ds.dataForFormat("items") as Array;
var r:int = tree.calculateDropIndex(event);
tree.selectedIndex = r;
var node:XML = tree.selectedItem as XML;
var p:*;
// if the selected node has children (it is type==city),
// then add the items at the beginning
if( tree.dataDescriptor.hasChildren(node) ) {
p = node;
r = 0;
} else {
p = node.parent();
}
for(var i:Number=0; i < items.length; i++) {
var insert:XML = <node />;
insert.@label = items[i];
insert.@type = "restaurant";
tree.dataDescriptor.addChildAt(p, insert, r+i);
}
}
/**
* Called when the drag operation completes, whether
* successfully or not. The tree is cleared of its
* selection.
*/
private function onDragComplete( event:DragEvent ) : void
{
tree.selectedIndex = -1;
}
]]>
</mx:Script>
<mx:XML id="treeData" xmlns="">
<root>
<node label="Massachusetts" type="state" data="MA">
<node label="Boston" type="city" >
<node label="Smoke House Grill" type="restaurant" />
<node label="Equator" type="restaurant" />
<node label="Aquataine" type="restaurant" />
<node label="Grill 23" type="restaurant" />
</node>
<node label="Provincetown" type="city" >
<node label="Lobster Pot" type="restaurant" />
<node label="The Mews" type="restaurant" />
</node>
</node>
<node label="California" type="state" data="CA">
<node label="San Francisco" type="city" >
<node label="Frog Lane" type="restaurant" />
</node>
</node>
</root>
</mx:XML>
<mx:Array id="listData">
<mx:String>Johnny Rocket's</mx:String>
<mx:String>Jet Pizza</mx:String>
<mx:String>Steve's Greek</mx:String>
<mx:String>Sonsie</mx:String>
<mx:String>The Border Cafe</mx:String>
</mx:Array>
<mx:Panel x="48" y="125" width="447" height="351" layout="absolute" title="Drag onto Tree">
<mx:Tree width="186" left="10" top="10" bottom="10" id="tree"
labelField="@label"
dataProvider="{treeData.node}"
dropEnabled="false"
dragMoveEnabled="false"
dragEnter="onDragEnter(event)"
dragOver="onDragOver(event)"
dragDrop="onDragDrop(event)">
</mx:Tree>
<mx:List width="188" height="206" right="10" bottom="10" id="list"
allowMultipleSelection="true"
dataProvider="{listData}"
dragEnabled="true"
dragMoveEnabled="true"
dragComplete="onDragComplete(event)">
</mx:List>
<mx:Text x="229" y="10" text="Drag from the list below to the tree" width="188" height="39"/>
<mx:Label x="229" y="69" text="restaurants"/>
</mx:Panel>
</mx:Application>
结果
发表评论
-
HBase技术介绍
2012-05-17 15:58 755http://www.searchtb.com/2011/01 ... -
使用JRockit Mission Control监控Java程序运行性能
2011-05-24 10:57 1527BEA的JRockit JDK是BEA公司自己开发的JDK。使 ... -
Myeclipse8.5 反编译插件 jad 安装
2010-09-25 15:11 1332准备工作 1.下载jad.exe文件:http://www. ... -
何谓系统架构师
2010-01-30 10:11 832首先,何谓系统架构师? IBM工程师的说明是: ... -
Flex开发RIA和WEB应用的5个建议
2009-12-31 16:02 11461.避免容器内嵌套其它容器,减少使用相对大小和相对位置 如果容 ... -
JPA 2.0 中的动态类型安全查询
2009-12-21 13:15 1714如果编译器能够对查询执行语法正确性检查,那么对于 Java 对 ... -
EJB3.0
2009-12-07 15:20 1642转自:http://hi.baidu.com/yaolihui ... -
一个简单的java Mail发送邮件程序
2009-12-06 12:01 1700package com.wisentsoft.manageme ... -
java Mail发送附件邮件
2009-12-04 13:25 3455利用Sun公司提供的JavaMail API可以很方便的开发邮 ... -
JMS服务器openJms入门
2009-11-25 10:46 1197首先可以到网站上下载 ...
相关推荐
Tree控件是Windows编程中常用的一种用户界面元素,主要用于展示层次结构的数据,如文件系统、...通过深入学习和实践这个例子,开发者可以掌握Tree控件的使用技巧,并了解到如何结合数据库来构建功能丰富的用户界面。
在Windows编程领域,控件是构建用户界面的基本元素,它们提供了与用户交互的方式。"多彩的自绘Tree控件"是一种特别设计的控件,它允许开发者为Tree控件定制丰富的视觉效果,使得应用程序的界面更加生动活泼,提升...
在IT领域,特别是前端开发中,用户界面的构建离不开各种控件的使用。"selectTree tree控件 日历控件 tree控件 radio CheckBox demo"这个标题揭示了几个关键的组件,它们是网页交互中的重要元素。下面将详细介绍这些...
将Tab控件和Tree控件联合使用,可以构建出更复杂的用户界面。例如,我们可以创建一个Tab控件,每个选项卡都包含一个独立的Tree控件,用于展示不同分类的数据。这样,用户可以轻松地在各个分类之间切换,同时每个分类...
在VC++中,"TREE 控件"是一种常用的图形用户界面(GUI)元素,它允许用户以树状结构来显示数据,通常用于组织层次化的信息。在本教程中,我们将深入探讨如何在VC++中使用TREE控件,以及它的一些关键特性和功能。 ...
总的来说,这个"VC++ TREE控件使用实例大全"集合涵盖了从基础到高级的各种使用案例,对于学习和掌握如何在VC++项目中有效地利用TREE控件是非常宝贵的资源。开发者可以通过研究这些示例代码,了解和掌握TREE控件的...
在C# WinForm开发中,有时我们可能需要创建自定义的控件来满足特定的界面需求,例如构建一个简单的Tree控件。这个教程将引导初学者如何从零开始实现一个基本的Tree控件,主要涉及的技术点包括自定义控件、事件处理...
VB Tree控件是Visual Basic(VB)编程环境中用于构建图形用户界面GUI的一种组件。它以树状结构显示数据,常用于文件系统浏览、菜单结构、层次关系数据展示等场景。在VB应用程序中,Tree控件提供了用户交互的方式,让...
Tree控件是Windows编程中常用的一种用户界面元素,主要用于展示层次结构的数据,如文件系统、组织结构等。在C++的MFC(Microsoft Foundation Classes)框架下,我们可以使用CTreeCtrl类来操作和管理Tree控件。这个...
在IT领域,尤其是在Windows应用程序开发中,MFC(Microsoft Foundation Classes)是一个强大的C++库,它简化了Windows API的使用,使开发者能够更方便地创建用户界面。本篇将深入探讨MFC中的对话框控件、List控件...
AngularJS,作为一款强大的前端JavaScript框架,提供了一种灵活的方式来构建动态、数据驱动的用户界面。在这个主题中,我们将深入探讨如何使用AngularJS创建自定义的Tree控件,并讨论其相关的重要概念和实现细节。 ...
在IT领域,"Tree控件"是一种常见的用户界面元素,用于展示层次结构的数据。它通常以节点和子节点的形式呈现,允许用户通过展开和...同时,理解并熟练掌握Tree控件的使用,对于开发高效、易用的用户界面具有重要意义。
在Labview中,我们可以从控件选板的“用户界面”类别下找到树形控件。将树形控件拖放到前面板上后,你可以开始自定义它的外观和行为。比如,可以设置控件的大小、颜色、字体等样式属性。同时,可以通过属性节点或...
- `ui`:用户界面相关的设置,如选中节点样式、拖放行为等。 - `types`:定义不同类型的节点,可以设置特定的图标和限制操作。 - `checkbox`:控制复选框的行为,如三态复选、全选/全不选等。 4. **数据源** - ...
在Windows编程领域,GUI(图形用户界面)设计中,控件是构建用户界面的基本元素,它们使得用户能够与应用程序进行交互。"Tree"和"List"控件是两种常见的控件类型,广泛应用于各种软件中,如文件管理器、设置面板等。...
总结来说,"Tree控件经验"这个主题涵盖了使用JavaScript进行高级程序设计的技术,尤其是如何利用这些技能来构建和优化用户界面中的Tree控件,这在现代Web应用开发中是非常重要的一部分。通过学习和实践这些知识,...
"利用Static控制自绘制作Tree控件"的主题是关于如何利用静态文本控件(Static)的自绘功能来实现一个定制化的树形控件。这种技术通常用于创建具有特定视觉样式或者需要额外功能的控件。 在Windows API中,`Static`...
在VC++开发环境中,使用Tree控件来构建一个类似Windows资源管理器的界面是一项常见的任务。这个过程涉及到对MFC(Microsoft Foundation Classes)框架的深入理解,尤其是对CTreeCtrl类的运用。CTreeCtrl是MFC提供的...
再者,"图标_tree控件"强调了在树型控件中使用图标的能力。图标可以增强视觉效果,帮助用户快速识别和理解节点的含义。比如,文件夹图标可以代表一个目录,文档图标可以表示具体的文件,不同的图标可以表示不同类型...
TreeCtrlTest展示了如何优雅地结合MFC的Tree控件和XML处理,提供了一个交互式的界面,让用户可以直观地查看和修改XML内容。 总结起来,“TreeCtrlTest”是一个优秀的MFC Tree控件应用实例,它结合了递归算法和XML...