- 浏览: 200546 次
- 性别:
- 来自: 上海
最新评论
-
zhuzhuaijq:
Flash OBJECT和EMBED标签详解 -
matt.u:
好像有点深奥。
一篇比较好演示AS的重构方法 -
luofeng113:
分析得不错,
flex编程感受 -
felixsky:
请问flexunit如何测试private和internal的 ...
FLEXUnit应用 -
wv1124:
你不能分个页啊,看得人都要死了
Apollo: 开发者问答录
关于组件拖放
可视化的开发环境就是要允许用户能够在屏幕中通过鼠标选择或者移动程序中的各种物件。拖放就允许用户选择一个物件,比如List控件或者Flex中的Image控件,然后把它拖到另外一个组件(容器),再把这个物件添加到这个组件(容器)中。
你可以添加对所有Flex组件拖放的支持,当然,Flex也本身包含了对拖放的built-in的支持和操作,比如List, Tree 和DataGrid控件,这些空间都能自动处理拖放所需要的操作。
关于拖放操作
拖放的操作包行三个主要的过程:初始化、拖以及放过程。
² 初始化:用户通过按下鼠标选择或者移动一个Flex组件,或者Flex组件中的一项来完成初始化动作。
² 拖:当用户仍然按住鼠标不放的时候,他可以在Flex程序中移动鼠标,拖的过程中所显示一个image就叫着一个drag proxy.它包含了被拖组件(drag source)的数据。
² 放:当用户把drag proxy移动到另外一个组件(容器),这个组件(容器)就成为了一个drop target.这个drop target就会检查drag source物件来判断里头的数据类型或者格式是否恩那个被drag target所接受。如果可以接受,即两种数据类型或者格式符合,就会允许用户放下所拖的组件。否则,则不允许用户放下组件。
执行拖放操作
拖和放都是事件驱动的。要配置一个组件作为drag initiator或者 drag target,你必须为特定的事件书写事件处理,比如dragDrop或者dragEnter事件。
一些经常被拖放的组件,Flex提供了Built-in事件处理来自动执行拖放操作。这些控件都是ListBase这个类的子类,可被认作为list-based控件。
对于移动操作,即你从drag initiator移动一个数据组件到drag target, list-based控件可以处理所有的拖放的时间处理。但是你如果要拷贝一个拖放组件数据到drop target,那么你就必须书写事件处理无论是list-based控件还是nonlist-based控件。
使用list-based控件
以下的控件都包行了对拖放的bulit-in的支持。
ü DataGrid
ü HorizontalList
ü List
ü PrintDataGrid
ü TileList
ü Tree
这些控件的built-in支持可以让用户从一个支持drag-enabled的控件把items移动到另外一个支持drop-enabled控件中。然而,要拷贝items,用户需要书写额外的逻辑操作。比如:以下的程序允许用户把List控件中的item移动到其他的控件中:
<?xml version="1.0"?>
<!-- dragdrop\SimpleListToListMove.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private function initApp():void {
srclist.dataProvider =
new ArrayCollection(['Reading', 'Television', 'Movies']);
destlist.dataProvider = new ArrayCollection([]);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Activities"/>
<mx:List id="srclist"
allowMultipleSelection="true"
dragEnabled="true"
dragMoveEnabled="true"/>
</mx:VBox>
<mx:VBox>
<mx:Label text="Activities I Like"/>
<mx:List id="destlist"
dropEnabled="true"/>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
通过设置第一个list的dragEnabled属性为true,以及第二个list中的dropEnabled属性为true,用户就可以从第一个list拖放item到第二个list,而不需要去担心底层是怎么执行的。
对于所有list类的控件除了Tree控件,dragMoveEnabled属性的值为false,所以你只能从一个控件拷贝元素到另外一个控件。通过设置第一个list中的dragMoveEnabled值为ture 你就可以移动或者拷贝数据了。对于Tree 控件,dragMoveEnabled的默认是为true的。
当dragMoveEnabled的值为ture的时候,拖放的默认执行操作是移动数据,如果要执行拷贝操作,在移动的过程中,通过按下Control 这个键就可以完成拷贝的操作。
在执行拖放的操作过程中,唯一的要求就是数据(data provider)的结构必须与两个控件要求的结构相符。否则将不能正确显示拖放的数据内容。
你可以更改托拖放的数据类型使得他们完成兼容的操作。以下的例子通过设置两个list-baed控件的dragEnabled,dropEnabled,和drogMoveEnabled属性值为ture来运行双向的拖放动作。
<?xml version="1.0"?>
<!-- dragdrop\SimpleDGToDG.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private function initApp():void {
srcgrid.dataProvider = new ArrayCollection([
{Artist:'Carole King', Album:'Tapestry', Price:11.99},
{Artist:'Paul Simon', Album:'Graceland', Price:10.99},
{Artist:'Original Cast', Album:'Camelot', Price:12.99},
{Artist:'The Beatles', Album:'The White Album', Price:11.99}
]);
destgrid.dataProvider = new ArrayCollection([]);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Albums"/>
<mx:DataGrid id="srcgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
同个控件中执行拖放操作
在同个控件中执行拖放操作一般是用来list-based控件中的item重组。下个例子当中,定义个Tree控件,允许用户通过拖放重组里面的节点。这个例子当中,你只需设置dragEnabled和dropEnabled两个属性为trure,因为Tree控件中的dragMoveEnabled的属性默认值为true.
<?xml version="1.0"?>
<!-- dragdrop\SimpleTreeSelf.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
// Initialize the data provider for the Tree.
private function initApp():void {
firstList.dataProvider = treeDP;
}
]]>
</mx:Script>
<mx:XML id="treeDP">
<node label="Mail">
<node label="Inbox"/>
<node label="Personal Folder">
<node label="Demo"/>
<node label="Personal"/>
<node label="Saved Mail"/>
<node label="bar"/>
</node>
<node label="Calendar"/>
<node label="Sent"/>
<node label="Trash"/>
</node>
</mx:XML>
<mx:Tree id="firstList"
showRoot="false"
labelField="@label"
dragEnabled="true"
dropEnabled="true"
allowMultipleSelection="true"
creationComplete="initApp();"/>
</mx:Application>
当然,list-based控件的拖放动作拥有很多属性值,具体可以参考development guide.这不多介绍了。
获取拷贝中的类型信息
当你利用list-based控件的built-in支持从一个list-based控件拷贝数据到另外一个list-based控件。你会碰见三种情形可能造成你的数据类型信息丢失。
Ø 当你在两个list-based控件中执行拷贝操作,但是在移动操作中并没有执行拷贝操作。
Ø 你的数据类型不是基本的AS数据类型,比如:Date,Number…
Ø 被拷贝的数据类型不是DispalyObject类,或者它的子类。
举例:你定义了一个如下的类,Car.as:
package
{
// dragdrop/Car.as
[RemoteClass]
public class Car extends Object
{
// Constructor.
public function Car()
{
super();
}
// Class properties.
public var numWheels:int;
public var model:String;
public var make:String;
public function get label():String
{
return make + " " + model;
}
}
}
注意到文件当中的元数据(metadata)标记 [RemoteClass].这个标记是用来注册一个Car数据类型,并且这个类型信息可以在拷贝过程中保留的。如果删除了这个标记,类型信息就会丢失了。然后你就可以在程序中利用这个类了:
<?xml version="1.0"?>
<!-- dragdrop\DandDRemoteClassListUpdated.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" xmlns="*">
<mx:Script>
<![CDATA[
public function changeit():void
{
if (list2.dataProvider != null)
{
msg.text += list2.dataProvider[0]
if(list2.dataProvider[0] is Car)
msg.text += " Is Car\n";
else
msg.text += " Is NOT Car\n";
}
}
]]>
</mx:Script>
<mx:List id="list1"
x="10" y="45"
width="160" height="120"
dragEnabled="true"
dragMoveEnabled="true">
<mx:dataProvider>
<mx:Array>
<Car model="Camry" make="Toyota" numWheels="4"/>
<Car model="Prius" make="Toyota" numWheels="4"/>
</mx:Array>
</mx:dataProvider>
</mx:List>
<mx:List id="list2"
x="200" y="45"
width="160" height="120"
dropEnabled="true"/>
<mx:Button label="Access it as button" click="changeit();"/>
<mx:TextArea id="msg"
x="10" y="200"
width="400" height="100"/>
</mx:Application>
手动增加拖放操作支持
Built-in的支持只适合于list-based的控件。但是Flex允许所有组件支持拖放操作。即一些nonlist-based的控件也可以执行拖放操作。这就需要处理拖放事件了。
支持拖放操作的类很多:包括DragManger,DragSource以及DragEvent。具体功能参考development guide. 同样对于draginitiator来说,也有很多drag-and-drop 事件:mouseDown,mouseMove,dragStart,dragComplete,dragEnter等。具体功能参考development guide。当为nonlist-based控件增加拖放操作支持时,必须实现事件处理:dragEnter和dragDrop两个事件。其他事件处理可选。对于list-based控件来说,当你设置了dropEnabled属性为true的时候,flex就自动增加了所有事件的处理。
拖放操作
以下的步骤定义了一个拖放操作:
Ø 一个组件成为一个课可拖放的initiator有两种方式:
ü List-based控件其dragEnabled值为ture.
ü Nonlist-based控件或者list-based控件其dragEnabled值为false的。程序必须检测用户的开始拖放的意图,一般的通过mouseMove或者mouseDown来开始一个拖放操作。接着组件必须创建一个—mx.core.DragSource 类实例包含要移动的数据以及数据格式。组件最后条用mx.manager.DragManager.doDrog()方法来出示一个拖放操作。
Ø 当鼠标仍然处于按下的状态,用户可以围绕应用程序界面移动鼠标,Flex将会在程序中显示一个代理镜像(proxy image)。DragManager.defaultDragImageSkin负责设置代理镜像的默认值。注意:当代理镜像没有在drag target上方时,若释放鼠标,flex将在drag initiator产上一个DragComplete事件,并且由DragManager.getFeedback()方法返回DragManger.NONE.
Ø 假如用户移动drag proxy经过一个flex组件,那么flex将调用dragEnter事件:
ü 对于dropEnabled=ture的list-base控件,flex检查看看组件时候能成为一个drop target.
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的。组件必须为dropEnter事件定义一个事件处理。这个事件处理能检查DragSource对象来决定是否数据可被接受与否。如果可以接受,事件处理将调用DragMnager.accetpDragDrop()方法。你必须为drag target调用这个方法来接收dragOver,dragEixt,dragDrop事件。
ü 如果drop target不接受,drop target组件的的父链将被检查是否可以任何组件可以接受这个drop data.
ü 如果drop target 或者其父链中的组件接受了drop。Flex将在用户移动proxy 到 drop target时候调用dragOver方法。
Ø 如果用户释放了鼠标执行放的操作。Flex将在drop target调用dragDrop事件.
ü 对于dropEnabled=ture的list-base控件,flex将自动添加drop data到drop target中。
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的, 在drop target必须定义对dragDrop事件的监听来处理增加drop data到drop target中。
例子:Nonlist-based组件的拖放操作
以下的例子是允许用户通过拖放两种颜色框来改变Canvas的背景颜色。
<?xml version="1.0"?>
<!-- dragdrop\DandDCanvas.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="white">
<mx:Script>
<![CDATA[
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.*;
import mx.containers.Canvas;
// Initializes the drag and drop operation.
private function mouseMoveHandler(event:MouseEvent):void {
// Get the drag initiator component from the event object.
var dragInitiator:Canvas=Canvas(event.currentTarget);
// Get the color of the drag initiator component.
var dragColor:int = dragInitiator.getStyle('backgroundColor');
// Create a DragSource object.
var ds:DragSource = new DragSource();
// Add the data to the object.
ds.addData(dragColor, 'color');
// Call the DragManager doDrag() method to start the drag.
DragManager.doDrag(dragInitiator, ds, event);
}
// Called when the user moves the drag proxy onto the drop target.
private function dragEnterHandler(event:DragEvent):void {
// Accept the drag only if the user is dragging data
// identified by the 'color' format value.
if (event.dragSource.hasFormat('color')) {
// Get the drop target component from the event object.
var dropTarget:Canvas=Canvas(event.currentTarget);
// Accept the drop.
DragManager.acceptDragDrop(dropTarget);
}
}
// Called if the target accepts the dragged object and the user
// releases the mouse button while over the Canvas container.
private function dragDropHandler(event:DragEvent):void {
// Get the data identified by the color format
// from the drag source.
var data:Object = event.dragSource.dataForFormat('color');
// Set the canvas color.
myCanvas.setStyle("backgroundColor", data);
}
]]>
</mx:Script>
<!-- A horizontal box with red and green canvases that the user can drag. -->
<mx:HBox>
<mx:Canvas
width="30" height="30"
backgroundColor="red"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
<mx:Canvas
width="30" height="30"
backgroundColor="green"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
</mx:HBox>
<mx:Label text="Drag a color onto the Canvas container."/>
<!-- Handles dragEnter and dragDrop events to allow dropping. -->
<mx:Canvas id="myCanvas"
width="100" height="100"
backgroundColor="#FFFFFF"
borderStyle="solid"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);"/>
<mx:Button id="b1"
label="Clear Canvas"
click="myCanvas.setStyle('backgroundColor', '0xFFFFFF');"
/>
</mx:Application>
简单描述鼠标mouseDown的事件处理:
1. 创建一个DragSource对象来初始化被拖放的数据以及类型。
2. 调用DragManger.doDrag()方法来开始拖放操作。
DragEnter事件处理:通过DataSource对象来判断被拖放的数据是否于drop target要求的类型兼容。
DragDrop事件处理:当释放鼠标的时候触发该事件,并且dragEnter事件已经掉哟个DragManger.acceptDragDrop()来接受drop.你必须定一个事件处理来把drop data添加到drop target中。
例子:处理list-based控件的拖放事件
当你设置了dragEnabled或者dropEnabled属性为ture时,Flex自动定义了默认的事件处理来执行拖放操作。当然你可以利用这些默认的事件处理,也可以自行定义你自己的事件处理。如果要定义自己的事件处理,必须在drag initiator设置dragEnabled属性为false,或者在drag target中设置dropEnabld为false.那如果要使用这些自己定义的事件处理,除了事先定义好之外,你最好需要显式停止flex默认的事件处理:即在你自己的事件处理中调用Event.preventDefault().注意:你如果在Tree控件中,当在移动一个data从一个tree控件到另外一个时候,你调用了Event.preventDefault()方法来处理dragComplete或者dragDrop事件,那么程序就会阻止drop操作。
以下的例子为dragDrop定义了一个事件处理。这个事件处理在默认的事件处理执行前执行来显式Alert信息。
<!-- dragdrop\SimpleDGToDGAlert.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
private function initApp():void {
srcgrid.dataProvider = new ArrayCollection([
{Artist:'Carole King', Album:'Tapestry', Price:11.99},
{Artist:'Paul Simon', Album:'Graceland', Price:10.99},
{Artist:'Original Cast', Album:'Camelot', Price:12.99},
{Artist:'The Beatles', Album:'The White Album', Price:11.99}
]);
destgrid.dataProvider = new ArrayCollection([]);
}
// Define the event listener.
public function dragDropHandler(event:DragEvent):void {
// dataForFormat() always returns an Array
// for the list-based controls
// in case multiple items were selected.
var dragObj:Array=
event.dragSource.dataForFormat("items") as Array;
// Get the Artist for all dragged albums.
var artistList:String='';
for (var i:Number = 0; i < dragObj.length; i++) {
artistList+='Artist: ' + dragObj[i].Artist + '\n';
}
Alert.show(artistList);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Albums"/>
<mx:DataGrid id="srcgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true"
dragDrop="dragDropHandler(event);">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
注意到了dataFormat()方法指定了一个参数名称items.这是因为list-based控件已经事先定义了drag data的数据格式。所有的list控件除了Tree控件,其格式字符为”items”,对于Tree控件来说其格式字符值为”treeItems”.还需要注意的是,dataFormat()方法返回的值是一个数组,这是因为list-based控件允许用户选择读多个items的缘故。
运行在AIR中的Flex应用程序的拖放
运行在AIR的中Flex程序可以使用Flex drag manager或者AIR drag Manger. Flex drag manager由 mx:mangers.DragManger类实现,而AIR drag Manger由flash.desktp.NativeDragManager类实现。默认的,Flex中由<mx:Application>定义的程序使用Flex drag-and drop manager.即使程序运行在AIR中,当然运行在AIR中的程序也可以制定使用AIR的drag-and-drop manager.这就需要配置Flex的 mx.managers.DragManger类,指定使用AIR中的drag-and-drop manger. 若使用<mx:WindowedApplicaiton>的Flex程序默认使用AIR的drag-and-drop 管理器。以下举例在<mx:Application>程序指定使用AIR中的drag-and-drop管理器:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="initDandD();">
<mx:Script>
<![CDATA[
// Ensure that the NativeDragManagerImpl class is linked in to your
application.
import mx.managers.NativeDragManagerImpl;
var placeholder:NativeDragManagerImpl;
// Handle the initialize event to load the DragManager.
public function initDandD():void
{
// Ensure the DragManager is loaded, so that dragging in an AIR works.
DragManager.isDragging;
}
]]>
</mx:Script>
...
</mx:Application>
拖放实例
例子1:用Canvas作为drop target
<?xml version="1.0"?>
<!-- dragdrop\DandDImage.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseMoveHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
DragManager.doDrag(dragInitiator, ds, event);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseMoveHandler(event);"/>
</mx:Canvas>
</mx:Application>
例子2:指定drag proxy
在事件处理mouseDown或者mouseUp中,你可以通过doDrag()来制定drag proxy.如果你不自己指定,哪么程序将使用默认值。你可以自行定义drag proxy以下属性:dragImage, xoffset, yoffset, imageAlpha.你必须制定drag proxy的大小,否则将不会被显示出来。举例:以下将设置proxy的长宽为15 pixel.
<?xml version="1.0"?>
<!-- dragdrop\DandDImageProxy.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseOverHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
// The drag manager uses the Image control
// as the drag proxy and sets the alpha to 1.0 (opaque),
// so it appears to be dragged across the Canvas.
var imageProxy:Image = new Image();
imageProxy.source = globeImage;
imageProxy.height=15;
imageProxy.width=15;
DragManager.doDrag(dragInitiator, ds, event,
imageProxy, -15, -15, 1.00);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseOverHandler(event);"/>
</mx:Canvas>
</mx:Application>
例子3:为drop target处理dragOver和dragExit事件
当用户移动鼠标到drop target,而它的dragEnter的事件已经调用DragManger.acceptDragDrop()方法时将会触发dragOver事件。当然这个事件是可选的。
dragOver事件相当有用尤其是当用户移动鼠标到drop target时能返回一个可视化的回馈。常使用的有:DragManager.COPY,DragManager.LINK,DragManager.MOVE,DragManager.NONE等。用户可以通过DragManger.showFeedback()方法来指定具体的显示形式。
dragExit是在用户在drop target放下drag proxy,但还没有放入数据时调度的。你可以利用这个方法来恢复之前因为dragOver事件所作的可视化的改变。
<?xml version="1.0"?>
<!-- dragdrop\DandDListToListShowFeedback.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.events.DragEvent;
import mx.collections.ArrayCollection;
private function initApp():void {
firstList.dataProvider = new ArrayCollection([
{label:"First", data:"1"},
{label:"Second", data:"2"},
{label:"Third", data:"3"},
{label:"Fourth", data:"4"}
]);
secondList.dataProvider = new ArrayCollection([]);
}
// Variable to store original border color.
private var tempBorderColor:uint;
// Flag to indicate that tempBorderColor has been set.
private var borderColorSet:Boolean = false;
private function dragOverHandler(event:DragEvent):void {
// Explpicitly handle the dragOver event.
event.preventDefault();
// Since you are explicitly handling the dragOver event,
// call showDropFeedback(event) to have the drop target
// display the drop indicator.
// The drop indicator is removed
// automatically for the list controls by the built-in
// event handler for the dragDrop event.
event.currentTarget.showDropFeedback(event);
if (event.dragSource.hasFormat("items"))
{
// Set the border to green to indicate that
// this is a drop target.
// Since the dragOver event is dispatched continuosly
// as you move over the drop target, only set it once.
if (borderColorSet == false) {
tempBorderColor =
event.currentTarget.getStyle('borderColor');
borderColorSet = true;
}
// Set the drag-feedback indicator based on the
// type of drag-and-drop operation.
event.currentTarget.setStyle('borderColor', 'green');
if (event.ctrlKey) {
DragManager.showFeedback(DragManager.COPY);
return;
}
else if (event.shiftKey) {
DragManager.showFeedback(DragManager.LINK);
return;
}
else {
DragManager.showFeedback(DragManager.MOVE);
return;
}
}
// Drag not allowed.
DragManager.showFeedback(DragManager.NONE);
}
private function dragDropHandler(event:DragEvent):void {
dragExitHandler(event);
}
// Restore the border color.
private function dragExitHandler(event:DragEvent):void {
event.currentTarget.setStyle('borderColor', tempBorderColor);
borderColorSet = true;
}
]]>
</mx:Script>
<mx:HBox id="myHB">
<mx:List id="firstList"
dragEnabled="true"
dragMoveEnabled="true"/>
<mx:List id="secondList"
borderThickness="2"
dropEnabled="true"
dragOver="dragOverHandler(event);"
dragDrop="dragExitHandler(event);"
dragExit="dragExitHandler(event);"/>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
移动和拷贝数据
移动和拷贝数据都是拖放操作的一部分。
关于移动数据
当你移动数据,是在drop target新增它,然后在drag initiator删除它来完成的。你利用dragDrop事件为drop target添加数据,利用dragComplete为drag initiator移除数据。而这个过程中你需要做多少工作取决于你使用的是list-based还是nonlist-based组件。
关于拷贝数据
List-based控件默认的是自动处理移除动作,所以你要做拷贝动作,你必须为drop target显式的处理dragDrop事件。
可视化的开发环境就是要允许用户能够在屏幕中通过鼠标选择或者移动程序中的各种物件。拖放就允许用户选择一个物件,比如List控件或者Flex中的Image控件,然后把它拖到另外一个组件(容器),再把这个物件添加到这个组件(容器)中。
你可以添加对所有Flex组件拖放的支持,当然,Flex也本身包含了对拖放的built-in的支持和操作,比如List, Tree 和DataGrid控件,这些空间都能自动处理拖放所需要的操作。
关于拖放操作
拖放的操作包行三个主要的过程:初始化、拖以及放过程。
² 初始化:用户通过按下鼠标选择或者移动一个Flex组件,或者Flex组件中的一项来完成初始化动作。
² 拖:当用户仍然按住鼠标不放的时候,他可以在Flex程序中移动鼠标,拖的过程中所显示一个image就叫着一个drag proxy.它包含了被拖组件(drag source)的数据。
² 放:当用户把drag proxy移动到另外一个组件(容器),这个组件(容器)就成为了一个drop target.这个drop target就会检查drag source物件来判断里头的数据类型或者格式是否恩那个被drag target所接受。如果可以接受,即两种数据类型或者格式符合,就会允许用户放下所拖的组件。否则,则不允许用户放下组件。
执行拖放操作
拖和放都是事件驱动的。要配置一个组件作为drag initiator或者 drag target,你必须为特定的事件书写事件处理,比如dragDrop或者dragEnter事件。
一些经常被拖放的组件,Flex提供了Built-in事件处理来自动执行拖放操作。这些控件都是ListBase这个类的子类,可被认作为list-based控件。
对于移动操作,即你从drag initiator移动一个数据组件到drag target, list-based控件可以处理所有的拖放的时间处理。但是你如果要拷贝一个拖放组件数据到drop target,那么你就必须书写事件处理无论是list-based控件还是nonlist-based控件。
使用list-based控件
以下的控件都包行了对拖放的bulit-in的支持。
ü DataGrid
ü HorizontalList
ü List
ü PrintDataGrid
ü TileList
ü Tree
这些控件的built-in支持可以让用户从一个支持drag-enabled的控件把items移动到另外一个支持drop-enabled控件中。然而,要拷贝items,用户需要书写额外的逻辑操作。比如:以下的程序允许用户把List控件中的item移动到其他的控件中:
<?xml version="1.0"?>
<!-- dragdrop\SimpleListToListMove.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private function initApp():void {
srclist.dataProvider =
new ArrayCollection(['Reading', 'Television', 'Movies']);
destlist.dataProvider = new ArrayCollection([]);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Activities"/>
<mx:List id="srclist"
allowMultipleSelection="true"
dragEnabled="true"
dragMoveEnabled="true"/>
</mx:VBox>
<mx:VBox>
<mx:Label text="Activities I Like"/>
<mx:List id="destlist"
dropEnabled="true"/>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
通过设置第一个list的dragEnabled属性为true,以及第二个list中的dropEnabled属性为true,用户就可以从第一个list拖放item到第二个list,而不需要去担心底层是怎么执行的。
对于所有list类的控件除了Tree控件,dragMoveEnabled属性的值为false,所以你只能从一个控件拷贝元素到另外一个控件。通过设置第一个list中的dragMoveEnabled值为ture 你就可以移动或者拷贝数据了。对于Tree 控件,dragMoveEnabled的默认是为true的。
当dragMoveEnabled的值为ture的时候,拖放的默认执行操作是移动数据,如果要执行拷贝操作,在移动的过程中,通过按下Control 这个键就可以完成拷贝的操作。
在执行拖放的操作过程中,唯一的要求就是数据(data provider)的结构必须与两个控件要求的结构相符。否则将不能正确显示拖放的数据内容。
你可以更改托拖放的数据类型使得他们完成兼容的操作。以下的例子通过设置两个list-baed控件的dragEnabled,dropEnabled,和drogMoveEnabled属性值为ture来运行双向的拖放动作。
<?xml version="1.0"?>
<!-- dragdrop\SimpleDGToDG.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private function initApp():void {
srcgrid.dataProvider = new ArrayCollection([
{Artist:'Carole King', Album:'Tapestry', Price:11.99},
{Artist:'Paul Simon', Album:'Graceland', Price:10.99},
{Artist:'Original Cast', Album:'Camelot', Price:12.99},
{Artist:'The Beatles', Album:'The White Album', Price:11.99}
]);
destgrid.dataProvider = new ArrayCollection([]);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Albums"/>
<mx:DataGrid id="srcgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
同个控件中执行拖放操作
在同个控件中执行拖放操作一般是用来list-based控件中的item重组。下个例子当中,定义个Tree控件,允许用户通过拖放重组里面的节点。这个例子当中,你只需设置dragEnabled和dropEnabled两个属性为trure,因为Tree控件中的dragMoveEnabled的属性默认值为true.
<?xml version="1.0"?>
<!-- dragdrop\SimpleTreeSelf.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
// Initialize the data provider for the Tree.
private function initApp():void {
firstList.dataProvider = treeDP;
}
]]>
</mx:Script>
<mx:XML id="treeDP">
<node label="Mail">
<node label="Inbox"/>
<node label="Personal Folder">
<node label="Demo"/>
<node label="Personal"/>
<node label="Saved Mail"/>
<node label="bar"/>
</node>
<node label="Calendar"/>
<node label="Sent"/>
<node label="Trash"/>
</node>
</mx:XML>
<mx:Tree id="firstList"
showRoot="false"
labelField="@label"
dragEnabled="true"
dropEnabled="true"
allowMultipleSelection="true"
creationComplete="initApp();"/>
</mx:Application>
当然,list-based控件的拖放动作拥有很多属性值,具体可以参考development guide.这不多介绍了。
获取拷贝中的类型信息
当你利用list-based控件的built-in支持从一个list-based控件拷贝数据到另外一个list-based控件。你会碰见三种情形可能造成你的数据类型信息丢失。
Ø 当你在两个list-based控件中执行拷贝操作,但是在移动操作中并没有执行拷贝操作。
Ø 你的数据类型不是基本的AS数据类型,比如:Date,Number…
Ø 被拷贝的数据类型不是DispalyObject类,或者它的子类。
举例:你定义了一个如下的类,Car.as:
package
{
// dragdrop/Car.as
[RemoteClass]
public class Car extends Object
{
// Constructor.
public function Car()
{
super();
}
// Class properties.
public var numWheels:int;
public var model:String;
public var make:String;
public function get label():String
{
return make + " " + model;
}
}
}
注意到文件当中的元数据(metadata)标记 [RemoteClass].这个标记是用来注册一个Car数据类型,并且这个类型信息可以在拷贝过程中保留的。如果删除了这个标记,类型信息就会丢失了。然后你就可以在程序中利用这个类了:
<?xml version="1.0"?>
<!-- dragdrop\DandDRemoteClassListUpdated.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" xmlns="*">
<mx:Script>
<![CDATA[
public function changeit():void
{
if (list2.dataProvider != null)
{
msg.text += list2.dataProvider[0]
if(list2.dataProvider[0] is Car)
msg.text += " Is Car\n";
else
msg.text += " Is NOT Car\n";
}
}
]]>
</mx:Script>
<mx:List id="list1"
x="10" y="45"
width="160" height="120"
dragEnabled="true"
dragMoveEnabled="true">
<mx:dataProvider>
<mx:Array>
<Car model="Camry" make="Toyota" numWheels="4"/>
<Car model="Prius" make="Toyota" numWheels="4"/>
</mx:Array>
</mx:dataProvider>
</mx:List>
<mx:List id="list2"
x="200" y="45"
width="160" height="120"
dropEnabled="true"/>
<mx:Button label="Access it as button" click="changeit();"/>
<mx:TextArea id="msg"
x="10" y="200"
width="400" height="100"/>
</mx:Application>
手动增加拖放操作支持
Built-in的支持只适合于list-based的控件。但是Flex允许所有组件支持拖放操作。即一些nonlist-based的控件也可以执行拖放操作。这就需要处理拖放事件了。
支持拖放操作的类很多:包括DragManger,DragSource以及DragEvent。具体功能参考development guide. 同样对于draginitiator来说,也有很多drag-and-drop 事件:mouseDown,mouseMove,dragStart,dragComplete,dragEnter等。具体功能参考development guide。当为nonlist-based控件增加拖放操作支持时,必须实现事件处理:dragEnter和dragDrop两个事件。其他事件处理可选。对于list-based控件来说,当你设置了dropEnabled属性为true的时候,flex就自动增加了所有事件的处理。
拖放操作
以下的步骤定义了一个拖放操作:
Ø 一个组件成为一个课可拖放的initiator有两种方式:
ü List-based控件其dragEnabled值为ture.
ü Nonlist-based控件或者list-based控件其dragEnabled值为false的。程序必须检测用户的开始拖放的意图,一般的通过mouseMove或者mouseDown来开始一个拖放操作。接着组件必须创建一个—mx.core.DragSource 类实例包含要移动的数据以及数据格式。组件最后条用mx.manager.DragManager.doDrog()方法来出示一个拖放操作。
Ø 当鼠标仍然处于按下的状态,用户可以围绕应用程序界面移动鼠标,Flex将会在程序中显示一个代理镜像(proxy image)。DragManager.defaultDragImageSkin负责设置代理镜像的默认值。注意:当代理镜像没有在drag target上方时,若释放鼠标,flex将在drag initiator产上一个DragComplete事件,并且由DragManager.getFeedback()方法返回DragManger.NONE.
Ø 假如用户移动drag proxy经过一个flex组件,那么flex将调用dragEnter事件:
ü 对于dropEnabled=ture的list-base控件,flex检查看看组件时候能成为一个drop target.
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的。组件必须为dropEnter事件定义一个事件处理。这个事件处理能检查DragSource对象来决定是否数据可被接受与否。如果可以接受,事件处理将调用DragMnager.accetpDragDrop()方法。你必须为drag target调用这个方法来接收dragOver,dragEixt,dragDrop事件。
ü 如果drop target不接受,drop target组件的的父链将被检查是否可以任何组件可以接受这个drop data.
ü 如果drop target 或者其父链中的组件接受了drop。Flex将在用户移动proxy 到 drop target时候调用dragOver方法。
Ø 如果用户释放了鼠标执行放的操作。Flex将在drop target调用dragDrop事件.
ü 对于dropEnabled=ture的list-base控件,flex将自动添加drop data到drop target中。
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的, 在drop target必须定义对dragDrop事件的监听来处理增加drop data到drop target中。
例子:Nonlist-based组件的拖放操作
以下的例子是允许用户通过拖放两种颜色框来改变Canvas的背景颜色。
<?xml version="1.0"?>
<!-- dragdrop\DandDCanvas.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="white">
<mx:Script>
<![CDATA[
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.*;
import mx.containers.Canvas;
// Initializes the drag and drop operation.
private function mouseMoveHandler(event:MouseEvent):void {
// Get the drag initiator component from the event object.
var dragInitiator:Canvas=Canvas(event.currentTarget);
// Get the color of the drag initiator component.
var dragColor:int = dragInitiator.getStyle('backgroundColor');
// Create a DragSource object.
var ds:DragSource = new DragSource();
// Add the data to the object.
ds.addData(dragColor, 'color');
// Call the DragManager doDrag() method to start the drag.
DragManager.doDrag(dragInitiator, ds, event);
}
// Called when the user moves the drag proxy onto the drop target.
private function dragEnterHandler(event:DragEvent):void {
// Accept the drag only if the user is dragging data
// identified by the 'color' format value.
if (event.dragSource.hasFormat('color')) {
// Get the drop target component from the event object.
var dropTarget:Canvas=Canvas(event.currentTarget);
// Accept the drop.
DragManager.acceptDragDrop(dropTarget);
}
}
// Called if the target accepts the dragged object and the user
// releases the mouse button while over the Canvas container.
private function dragDropHandler(event:DragEvent):void {
// Get the data identified by the color format
// from the drag source.
var data:Object = event.dragSource.dataForFormat('color');
// Set the canvas color.
myCanvas.setStyle("backgroundColor", data);
}
]]>
</mx:Script>
<!-- A horizontal box with red and green canvases that the user can drag. -->
<mx:HBox>
<mx:Canvas
width="30" height="30"
backgroundColor="red"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
<mx:Canvas
width="30" height="30"
backgroundColor="green"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
</mx:HBox>
<mx:Label text="Drag a color onto the Canvas container."/>
<!-- Handles dragEnter and dragDrop events to allow dropping. -->
<mx:Canvas id="myCanvas"
width="100" height="100"
backgroundColor="#FFFFFF"
borderStyle="solid"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);"/>
<mx:Button id="b1"
label="Clear Canvas"
click="myCanvas.setStyle('backgroundColor', '0xFFFFFF');"
/>
</mx:Application>
简单描述鼠标mouseDown的事件处理:
1. 创建一个DragSource对象来初始化被拖放的数据以及类型。
2. 调用DragManger.doDrag()方法来开始拖放操作。
DragEnter事件处理:通过DataSource对象来判断被拖放的数据是否于drop target要求的类型兼容。
DragDrop事件处理:当释放鼠标的时候触发该事件,并且dragEnter事件已经掉哟个DragManger.acceptDragDrop()来接受drop.你必须定一个事件处理来把drop data添加到drop target中。
例子:处理list-based控件的拖放事件
当你设置了dragEnabled或者dropEnabled属性为ture时,Flex自动定义了默认的事件处理来执行拖放操作。当然你可以利用这些默认的事件处理,也可以自行定义你自己的事件处理。如果要定义自己的事件处理,必须在drag initiator设置dragEnabled属性为false,或者在drag target中设置dropEnabld为false.那如果要使用这些自己定义的事件处理,除了事先定义好之外,你最好需要显式停止flex默认的事件处理:即在你自己的事件处理中调用Event.preventDefault().注意:你如果在Tree控件中,当在移动一个data从一个tree控件到另外一个时候,你调用了Event.preventDefault()方法来处理dragComplete或者dragDrop事件,那么程序就会阻止drop操作。
以下的例子为dragDrop定义了一个事件处理。这个事件处理在默认的事件处理执行前执行来显式Alert信息。
<!-- dragdrop\SimpleDGToDGAlert.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
private function initApp():void {
srcgrid.dataProvider = new ArrayCollection([
{Artist:'Carole King', Album:'Tapestry', Price:11.99},
{Artist:'Paul Simon', Album:'Graceland', Price:10.99},
{Artist:'Original Cast', Album:'Camelot', Price:12.99},
{Artist:'The Beatles', Album:'The White Album', Price:11.99}
]);
destgrid.dataProvider = new ArrayCollection([]);
}
// Define the event listener.
public function dragDropHandler(event:DragEvent):void {
// dataForFormat() always returns an Array
// for the list-based controls
// in case multiple items were selected.
var dragObj:Array=
event.dragSource.dataForFormat("items") as Array;
// Get the Artist for all dragged albums.
var artistList:String='';
for (var i:Number = 0; i < dragObj.length; i++) {
artistList+='Artist: ' + dragObj[i].Artist + '\n';
}
Alert.show(artistList);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Albums"/>
<mx:DataGrid id="srcgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true"
dragDrop="dragDropHandler(event);">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
注意到了dataFormat()方法指定了一个参数名称items.这是因为list-based控件已经事先定义了drag data的数据格式。所有的list控件除了Tree控件,其格式字符为”items”,对于Tree控件来说其格式字符值为”treeItems”.还需要注意的是,dataFormat()方法返回的值是一个数组,这是因为list-based控件允许用户选择读多个items的缘故。
运行在AIR中的Flex应用程序的拖放
运行在AIR的中Flex程序可以使用Flex drag manager或者AIR drag Manger. Flex drag manager由 mx:mangers.DragManger类实现,而AIR drag Manger由flash.desktp.NativeDragManager类实现。默认的,Flex中由<mx:Application>定义的程序使用Flex drag-and drop manager.即使程序运行在AIR中,当然运行在AIR中的程序也可以制定使用AIR的drag-and-drop manager.这就需要配置Flex的 mx.managers.DragManger类,指定使用AIR中的drag-and-drop manger. 若使用<mx:WindowedApplicaiton>的Flex程序默认使用AIR的drag-and-drop 管理器。以下举例在<mx:Application>程序指定使用AIR中的drag-and-drop管理器:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="initDandD();">
<mx:Script>
<![CDATA[
// Ensure that the NativeDragManagerImpl class is linked in to your
application.
import mx.managers.NativeDragManagerImpl;
var placeholder:NativeDragManagerImpl;
// Handle the initialize event to load the DragManager.
public function initDandD():void
{
// Ensure the DragManager is loaded, so that dragging in an AIR works.
DragManager.isDragging;
}
]]>
</mx:Script>
...
</mx:Application>
拖放实例
例子1:用Canvas作为drop target
<?xml version="1.0"?>
<!-- dragdrop\DandDImage.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseMoveHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
DragManager.doDrag(dragInitiator, ds, event);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseMoveHandler(event);"/>
</mx:Canvas>
</mx:Application>
例子2:指定drag proxy
在事件处理mouseDown或者mouseUp中,你可以通过doDrag()来制定drag proxy.如果你不自己指定,哪么程序将使用默认值。你可以自行定义drag proxy以下属性:dragImage, xoffset, yoffset, imageAlpha.你必须制定drag proxy的大小,否则将不会被显示出来。举例:以下将设置proxy的长宽为15 pixel.
<?xml version="1.0"?>
<!-- dragdrop\DandDImageProxy.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// initiates the drag-and-drop operation.
private function mouseOverHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
// The drag manager uses the Image control
// as the drag proxy and sets the alpha to 1.0 (opaque),
// so it appears to be dragged across the Canvas.
var imageProxy:Image = new Image();
imageProxy.source = globeImage;
imageProxy.height=15;
imageProxy.width=15;
DragManager.doDrag(dragInitiator, ds, event,
imageProxy, -15, -15, 1.00);
}
// The dragEnter event handler for the Canvas container
// enables dropping.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY;
}
]]>
</mx:Script>
<!-- The Canvas is the drag target -->
<mx:Canvas id="v1"
width="500" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);">
<!-- The image is the drag initiator. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseOverHandler(event);"/>
</mx:Canvas>
</mx:Application>
例子3:为drop target处理dragOver和dragExit事件
当用户移动鼠标到drop target,而它的dragEnter的事件已经调用DragManger.acceptDragDrop()方法时将会触发dragOver事件。当然这个事件是可选的。
dragOver事件相当有用尤其是当用户移动鼠标到drop target时能返回一个可视化的回馈。常使用的有:DragManager.COPY,DragManager.LINK,DragManager.MOVE,DragManager.NONE等。用户可以通过DragManger.showFeedback()方法来指定具体的显示形式。
dragExit是在用户在drop target放下drag proxy,但还没有放入数据时调度的。你可以利用这个方法来恢复之前因为dragOver事件所作的可视化的改变。
<?xml version="1.0"?>
<!-- dragdrop\DandDListToListShowFeedback.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.events.DragEvent;
import mx.collections.ArrayCollection;
private function initApp():void {
firstList.dataProvider = new ArrayCollection([
{label:"First", data:"1"},
{label:"Second", data:"2"},
{label:"Third", data:"3"},
{label:"Fourth", data:"4"}
]);
secondList.dataProvider = new ArrayCollection([]);
}
// Variable to store original border color.
private var tempBorderColor:uint;
// Flag to indicate that tempBorderColor has been set.
private var borderColorSet:Boolean = false;
private function dragOverHandler(event:DragEvent):void {
// Explpicitly handle the dragOver event.
event.preventDefault();
// Since you are explicitly handling the dragOver event,
// call showDropFeedback(event) to have the drop target
// display the drop indicator.
// The drop indicator is removed
// automatically for the list controls by the built-in
// event handler for the dragDrop event.
event.currentTarget.showDropFeedback(event);
if (event.dragSource.hasFormat("items"))
{
// Set the border to green to indicate that
// this is a drop target.
// Since the dragOver event is dispatched continuosly
// as you move over the drop target, only set it once.
if (borderColorSet == false) {
tempBorderColor =
event.currentTarget.getStyle('borderColor');
borderColorSet = true;
}
// Set the drag-feedback indicator based on the
// type of drag-and-drop operation.
event.currentTarget.setStyle('borderColor', 'green');
if (event.ctrlKey) {
DragManager.showFeedback(DragManager.COPY);
return;
}
else if (event.shiftKey) {
DragManager.showFeedback(DragManager.LINK);
return;
}
else {
DragManager.showFeedback(DragManager.MOVE);
return;
}
}
// Drag not allowed.
DragManager.showFeedback(DragManager.NONE);
}
private function dragDropHandler(event:DragEvent):void {
dragExitHandler(event);
}
// Restore the border color.
private function dragExitHandler(event:DragEvent):void {
event.currentTarget.setStyle('borderColor', tempBorderColor);
borderColorSet = true;
}
]]>
</mx:Script>
<mx:HBox id="myHB">
<mx:List id="firstList"
dragEnabled="true"
dragMoveEnabled="true"/>
<mx:List id="secondList"
borderThickness="2"
dropEnabled="true"
dragOver="dragOverHandler(event);"
dragDrop="dragExitHandler(event);"
dragExit="dragExitHandler(event);"/>
</mx:HBox>
<mx:Button id="b1"
label="Reset"
click="initApp()"
/>
</mx:Application>
移动和拷贝数据
移动和拷贝数据都是拖放操作的一部分。
关于移动数据
当你移动数据,是在drop target新增它,然后在drag initiator删除它来完成的。你利用dragDrop事件为drop target添加数据,利用dragComplete为drag initiator移除数据。而这个过程中你需要做多少工作取决于你使用的是list-based还是nonlist-based组件。
关于拷贝数据
List-based控件默认的是自动处理移除动作,所以你要做拷贝动作,你必须为drop target显式的处理dragDrop事件。
发表评论
-
pv3d学习资料
2009-08-13 14:54 1870官方网站 http://www.papervision3d.c ... -
Flash客户端间的交互
2009-08-13 14:35 3065Flash有着天生非凡的动画和交互能力, 在RIA (富互联网 ... -
ItemRenderer的用法
2009-01-14 13:59 1811项目渲染器(ItemRenderer ... -
基于MVC的Flex framework比较
2008-08-13 10:13 1591关键字: mvc framework 原文出处:[url]h ... -
色彩模式(RGB、CMYK、HSB、Lab、Duotone等)
2008-08-05 13:10 3787色彩是一门很深的学问,每种色彩都有自己的特点和原理。设计师要在 ... -
colormatrixFilter
2008-07-31 12:38 1136http://hi.baidu.com/fmz1206/blo ... -
使用BlazeDS实现Java和Flex通信
2008-06-16 09:21 1053http://blog.chinaunix.net/u/216 ... -
amf是什么东东
2008-06-12 16:59 1351今天我们开发的 J2EE 网 ... -
Flash特效制作常用的源代码大放送
2008-06-06 16:02 1093对象数组 比如要构建一个有很多属性的数组,简单的可以这样 ... -
编写时间轴代码代码规范
2008-06-06 15:34 1163For any major project, you co ... -
关于ApplicationDomain的一些理解
2008-06-05 17:07 2864应用程序域: 允许跨域加载swf后,还可能出现加载的swf中的 ... -
Flash OBJECT和EMBED标签详解
2008-06-05 17:03 31118Flash OBJECT和EMBED标签 一 ... -
flex的一些项目
2008-06-03 14:48 1323一些Flex开源项目的整理 Adobe APIs 主要包 ... -
flex模式(转载)
2008-06-03 14:28 1532[url] http://www.awflasher.com/ ... -
programming Flex2 学习笔记-第5章-框架基础.txt (转载的,来自)
2008-05-29 10:40 1267来自http://blog.chinaunix.net ... -
给DataGrid设置背景色(汇总)
2008-05-27 16:49 5041DataGrid颜色专题 在Flex运用中经常提到的有关 ... -
通过ApplicationDomain类获得被加载应用程序域
2008-05-27 13:32 1640首先先回顾一下FLASH的OO ... -
一些Flex / Flash开源项目
2008-05-09 14:26 1547Adobe APIs 主要包含corelib, ... -
这几个网站是我经常去的,做开发时可以参考
2008-05-09 14:14 1403http://www.flashas.net/ http:// ... -
108种Flash常见问题解答(收藏别的:站名:http://www.flashas.net/)
2008-05-09 14:09 24251. 论坛上常说的MC、FS、 ...
相关推荐
Flex3 是Adobe Flash平台的一个版本,它提供了丰富的用户界面组件和强大的数据绑定功能...这个教程“Flex3+组件拖放教程--一路风尘.pdf”很可能会详细解释这些概念,并通过实例代码展示如何在实际项目中运用这些技术。
Flex 3 是 Adobe 开发的一款用于构建富互联网应用程序(RIA)的框架,它基于 ActionScript 3 和 MXML。...此外,对于复杂的拖放场景,你可能需要利用 Flex 3 的事件模型和组件树结构,以便在不同组件之间协调拖放行为。
这个实例涉及的是在Flex中的Tree组件实现节点的内部拖放功能,这对于创建交互式用户界面,尤其是数据层级结构的展示非常有用。在本文中,我们将详细探讨如何在Flex的Tree组件中实现节点的拖放操作,并且限制可拖动的...
《Flex3 Java 中文教程》是一本专注于Adobe Flex 3技术的中文教程,结合了Java技术和Adobe Integrated Runtime(AIR)的应用,旨在帮助开发者深入理解和掌握使用Flex 3进行富互联网应用(RIA)开发的方法和技巧。...
这些组件可以扩展标准的Flex组件库,或者从头开始构建,以提供独特的功能和视觉表现。 在标题“各种Flex自定义组件”中,我们可以推断这是一个包含多种定制Flex组件的资源集合。这些组件可能包括时间选择器、数据...
在Flex组件库的学习中,读者将了解到如何使用各种预定义的UI组件,如按钮、文本输入框、面板等,来构建用户界面。同时,教程还会教授如何自定义组件以满足特定项目需求。 对于AIR应用程序的开发,教程会涉及AIR SDK...
要深入学习Flex Explorer组件,可以参考Adobe官方文档、在线教程、开发者论坛以及相关书籍。实践中不断尝试和调试,理解其工作原理,将有助于更好地利用此组件来提升用户体验。 总之,Flex Explorer组件是构建数据...
通过这个Flex3基础教程PPT,初学者不仅可以学习到Flex3的基本语法和组件使用,还能深入理解事件处理、数据绑定等核心概念,为开发复杂的富互联网应用打下坚实基础。对于每个主题,PPT通常会结合实例演示,帮助学习者...
4. **Flex组件模型**:Flex组件是可重用的UI元素,如Button、TextArea、Canvas等。这些组件基于Flex组件模型,允许自定义样式、行为和功能。开发者可以通过继承和扩展已有组件来创建自己的定制组件。 5. **数据绑定...
Flex组件拖拽框架是一种在Adobe Flex环境中实现的交互设计技术,允许用户通过鼠标操作将组件在界面上自由移动,从而提升用户体验和应用的可操作性。这个框架通常由一系列类和方法组成,用于处理拖放事件,跟踪鼠标...
"flex组件之其他组件实例源码"这个主题涵盖了一些非基本但非常实用的Flex组件,如高级数据格、打印、视频播放等,这些都是在开发复杂应用时不可或缺的部分。 首先,高级数据格(Advanced Data Grid)是Flex中一个...
本教程将详细介绍如何在Flex 4.5中实现Tree组件与任意组件之间的拖放操作,特别是将树形结构的数据拖拽到DataGrid中,并获取目标位置的全部数据进行添加。 1. **Flex 4.5的DragManager和DropTarget** Flex 4.5中的...
本教程将深入讲解Flex Tree组件的使用方法和关键概念,帮助开发者更好地理解和应用这一功能强大的工具。 在Flex中,Tree组件是基于MX组件集的一部分,它允许用户通过节点展开和折叠来探索层级数据。每个节点可以...
5. **Flex组件**:Flex提供了大量的预定义组件,如按钮、列表、数据网格等,这些组件可以方便地拖放到设计视图中,大大简化了UI开发。 6. **数据绑定**:Flex中的数据绑定允许UI元素与数据源直接关联,当数据源变化...
3. **数据绑定**:Flex支持数据绑定,这意味着你可以将拓扑图的结构与数据模型关联起来。通过改变数据模型,拓扑图的显示会自动更新,反之亦然,这大大简化了复杂图表的管理。 4. **自定义组件**:拓扑图组件通常...
3. **错误处理**:当上传失败时,组件可以提供错误信息,并允许用户重新尝试。 4. **文件大小限制**:可以设置上传文件的最大大小,防止过大文件导致服务器压力。 5. **文件类型过滤**:允许设定允许上传的文件类型...
5. 拖放组件:允许用户在界面上进行拖放操作,常用于文件管理或数据组织应用。 6. 表格和列表增强:提供更灵活的数据展示方式,可能包括排序、过滤、分组、多列选择等功能。 7. 日历和时间选择器:方便用户选择...
在Flex中,拖放(Drag and Drop)功能是一个常见的用户交互模式,允许用户通过鼠标操作将一个对象从一个位置移动到另一个位置,通常在不同的组件之间。这种功能在各种类型的应用程序中都很常见,例如文件管理器、...
在Flex3中,你可以创建具有丰富用户界面和交互功能的应用程序,而“flex3一个简单购物车拖拽的例子”是一个演示如何在Flex环境中实现拖放功能的实例。这个例子展示了如何将商品图标或项拖入数据网格(DataGrid)中,...