リストコントロールではドラッグ&ドロップがビルトインでサポートされていますが、ドラッグ&ドロップはどの Flex コンポーネントでも使用できます。非リストコンポーネントでドラッグ&ドロップをサポートしたり、リストコントロールで明示的にドラッグ&ドロップを制御したりするには、ドラッグ&ドロップイベントを処理する必要があります。
次のクラスを使用してドラッグ&ドロップ操作を実装します。
|
クラス |
機能 |
|---|---|
|
ドラッグ&ドロップ操作を管理します。例えば、doDrag() メソッドはドラッグ操作を開始します。 |
|
|
ドラッグされるデータを格納します。他のドラッグ管理機能として、データが要求されたときに呼び出されるハンドラを追加する機能なども提供します。 |
|
|
すべてのドラッグ&ドロップイベントのイベントオブジェクトを表します。 |
ドラッグイニシエータとなるコンポーネントが、次のイベントを処理してドラッグ&ドロップ操作を管理します。
|
ドラッグイニシエータイベント |
説明 |
ハンドラの必要性 |
リストコントロールによる実装 |
|---|---|---|---|
|
mouseDown および mouseMove |
mouseDown イベントは、ユーザーがマウスでコントロールを選択し、マウスボタンを押したままにすると送出されます。mouseMove イベントは、マウスが移動したときに送出されます。 |
必要(リストコントロールではない場合) |
なし |
|
dragStart |
ドラッグ操作が開始されたときに、リストコンポーネントにより送出されます。このイベントは、リストコントロールで内部的に使用されます。ドラッグ&ドロップを実装する際にこのイベントを処理する必要はありません。 ドラッグ&ドロップ操作の開始を制御する場合は、mouseDown イベントまたは mouseMove イベントを使用します。 |
必要(リストコントロールの場合) |
あり |
|
dragComplete |
ドラッグ操作が完了したとき(ドラッグデータをドロップターゲットにドロップするか、ドロップを実行せずにドラッグ&ドロップ操作を終了したとき)に送出されます。 このイベントは、ドラッグ&ドロップ操作の最終的なクリーンアップを行うために使用できます。例えば、ユーザーがデータをあるコンポーネントから他のコンポーネントに移動した場合、このイベントを使用して、そのアイテムをドラッグイニシエータから削除できます。例については、例:非リストコントロールでのデータの移動とコピーを参照してください。 |
不要 |
あり |
コンポーネントにドラッグ&ドロップのサポートを追加する場合、mouseDown イベントまたは mouseMove イベントのいずれかに対するイベントハンドラを実装する必要があります。また、オプションで dragComplete イベントに対するイベントハンドラを実装します。リストコントロールの dragEnabled プロパティを true に設定すると、Flex では dragStart および dragComplete イベントのイベントハンドラが自動的に追加されます。
コンポーネントをドロップターゲットとして使用する場合は、次のイベントを処理します。
|
ドロップターゲットイベント |
説明 |
ハンドラの必要性 |
リストコントロールによる実装 |
|---|---|---|---|
|
dragEnter |
ドラッグプロキシがドロップターゲットの外側からドロップターゲット上に移動したときに送出されます。 コンポーネントをドロップターゲットにするには、このイベントに対するイベントハンドラを定義する必要があります。イベントハンドラでは、ドラッグされているデータが受け付けられるフォーマットであるかどうかを判断します。ドロップを受け付ける場合は、イベントハンドラによって DragManager.acceptDragDrop() メソッドが呼び出されます。ドロップターゲットが dragOver イベント、dragExit イベントおよび dragDrop イベントを受け取るようにするには、DragManager.acceptDragDrop() メソッドを呼び出す必要があります。 ハンドラ内では、コンポーネントがドラッグ操作を受け付けることができることを示す視覚的なフィードバックをユーザーに提供するために、ドロップターゲットの外観を変更できます。例えば、ドロップターゲットの周囲に境界線を表示したり、ドロップターゲットにフォーカスを移すことができます。例については、例:非リストコントロールでの単純なドラッグ&ドロップ操作を参照してください。 |
必要 |
あり |
|
dragOver |
dragEnter イベント後に、ユーザーがターゲット上でマウスを移動したときに送出されます。 このイベントは、ドロップ操作を許可する前に追加のロジックを実行する場合に使用します。追加のロジックの例としては、ドロップターゲット内のいろいろな場所にデータをドロップする操作、キーボード入力を読み取って、ドラッグ&ドロップ操作がドラッグデータの移動またはコピーのどちらであるかを判別する操作、ドラッグ&ドロップ操作のタイプに基づいて異なるタイプの視覚的なフィードバックを提供する操作などがあります。例については、例:ドロップターゲットの dragOver イベントおよび dragExit イベントの処理を参照してください。 |
不要 |
あり |
|
dragDrop |
ユーザーがドロップターゲット上でマウスボタンを離したときに送出されます。 このイベントハンドラは、ドラッグデータをドロップターゲットに追加するために使用します。例については、例:非リストコントロールでの単純なドラッグ&ドロップ操作を参照してください。 |
必要 |
あり |
|
dragExit |
ユーザーがドラッグプロキシをドロップターゲットの外側に移動し、ターゲットにドロップしないときに送出されます。 このイベントは、dragEnter イベントや他のイベントに対応してドロップターゲットの外観を変更した場合に、ドロップターゲットを通常の外観に復元するのに使用できます。例については、例:ドロップターゲットの dragOver イベントおよび dragExit イベントの処理を参照してください。 |
不要 |
あり |
非リストコンポーネントにドラッグ&ドロップのサポートを追加する場合、dragEnter イベントおよび dragDrop イベントに対するイベントハンドラを実装する必要があります。また、オプションで他のイベントに対するイベントハンドラを実装します。リストコントロールの dropEnabled プロパティを true に設定すると、Flex ではすべてのイベントのイベントハンドラが自動的に追加されます。
ドラッグ&ドロップ操作は、次の手順で定義されます。
ユーザーがマウスをコンポーネント上でクリックして移動すると、Flex によってそのコンポーネントが自動的にイニシエータになります。
コンポーネントは、ユーザーがドラッグ操作を開始しようとしていることを検出し、明示的にイニシエータになる必要があります。一般的には、mouseMove イベントまたは mouseDown イベントを使用してドラッグ&ドロップ操作を開始します。
コンポーネントによって、ドラッグされるデータを含む mx.core.DragSource クラスのインスタンスが作成され、データのフォーマットが指定されます。
さらに、コンポーネントによって mx.managers.DragManager.doDrag() メソッドが呼び出され、ドラッグ&ドロップ操作が開始されます。
独自のドラッグプロキシイメージを定義できます。詳細については、例:ドラッグプロキシの指定を参照してください。
Flex によって、コンポーネントがドロップターゲットになれるかどうかが確認されます。
コンポーネントをドロップターゲットとするには、dragEnter イベントのイベントハンドラを定義する必要があります。
dragEnter イベントハンドラによって DragSource オブジェクトが調べられ、ドラッグされているデータが受け付けられるデータフォーマットかどうか判断されます。ドロップを受け付ける場合は、イベントハンドラによって DragManager.acceptDragDrop() メソッドが呼び出されます。ドロップターゲットに対して DragManager.acceptDragDrop() メソッドを呼び出して、dragOver、dragExit、および dragDrop の各イベントを受け取る必要があります。
Flex では、ドラッグデータがドロップターゲットに自動的に追加されます。コピー操作の場合は、リストコントローラに対する dragDrop イベントのイベントハンドラを実装する必要があります。詳細については、例:ある List コントロールから別の List コントロールへのデータのコピーを参照してください。
ドロップターゲットは dragDrop イベントハンドラのイベントリスナーを定義して、ドラッグデータをドロップターゲットに追加する必要があります。
移動操作の場合、ドラッグデータがドラッグイニシエータから自動的に削除されます。
ドラッグイニシエータは、必要な最終処理のすべてを完了します。移動操作の場合、イベントハンドラがドラッグデータをドラッグイニシエータから削除する必要があります。dragComplete イベントに対するイベントハンドラの記述例については、例:非リストコントロールでのデータの移動とコピーを参照してください。
次の例では、Canvas コンテナに 2 つの色のいずれかをドロップすることにより、コンテナの背景色を設定します。データのコピーや移動は行いません。代わりに、2 つのドラッグイニシエータをカラーパレットとして使用します。次に、1 つのパレットから色をドラッグしてターゲットにドロップし、背景色を設定します。
2 つの Canvas コンテナのドラッグイニシエータは、mouseDown イベントに対するイベントハンドラを実装して、ドラッグ&ドロップ操作を開始します。これは、ドラッグイニシエータによって処理される必要のある唯一のイベントです。ドロップターゲットでは、dragEnter イベントおよび dragDrop イベントのイベントハンドラを実装する必要があります。
<?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 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:Application>
前の例で実行する SWF ファイルは以下のとおりです。
以降のセクションでは、mouseDown イベント、dragEnter イベントおよび dragDrop イベントのイベントハンドラについて説明します。
ドラッグ&ドロップ操作を開始するイベントハンドラでは、2 つのことを行う必要があります。
DragSource オブジェクトには、ドラッグデータと、データフォーマットと呼ばれるドラッグデータの説明が格納されます。dragEnter イベントおよび dragDrop イベントのイベントオブジェクトには、このオブジェクトへの参照が dragSource プロパティに格納されます。イベントハンドラはこのプロパティを使用することにより、ドラッグデータにアクセスできます。
DragSource.addData() メソッドを使用してドラッグデータとフォーマットを DragSource オブジェクトに追加します。ここで、addData() メソッドは、次のシグネチャを持ちます。
addData(data:Object, format:String):void
format パラメータは、"color"、"list data",、"employee record". などのテキストストリングです。dragEnter イベントのイベントハンドラでは、ドロップターゲットがこのストリングを調べて、データフォーマットがドロップターゲットで受け付けるデータの型に一致しているかどうか判断します。受け付けられるフォーマットの場合は、ドロップターゲットにデータをドロップできます。そうでない場合には、ドロップ操作は許可されません。
フォーマットストリングを使用する 1 つの例としては、アプリケーションにドロップターゲットとして機能する複数のコンポーネントがある場合が挙げられます。各ドロップターゲットは、その dragEnter イベントの間に DragSource オブジェクトを調べて、そのドロップターゲットがそのフォーマットをサポートするかどうかを判断します。詳細については、dragEnter イベントの処理を参照してください。
大量または複雑なデータアイテムをドラッグする場合は、データをコピーするハンドラを作成し、DragSource.addData() メソッドではなく、DragSource.addListener() メソッドを呼び出して、作成したハンドラを指定することができます。この場合、ユーザーがデータをドロップするまで、データがコピーされないので、ドラッグし始めたデータをユーザーがドロップしない場合に発生するデータコピー処理のオーバーヘッドが抑制されます。リストクラスの実装には、この手法を使用します。
doDrag() メソッドのシグネチャを次に示します。
doDrag(dragInitiator:IUIComponent, dragSource:DragSource, mouseEvent:MouseEvent,
dragImage:IFlexDisplayObject = null, xOffset:Number = 0, yOffset:Number = 0,
imageAlpha:Number = 0.5, allowMove:Boolean = true):void
doDrag() メソッドには 3 つの引数、つまりドラッグ操作を開始するコンポーネントへの参照(event.currentTarget オブジェクトにより識別)、手順 1 で作成した DragSource オブジェクト、およびイベントハンドラに渡されたイベントオブジェクトが必要です。
オプションのパラメータを使用すると、ドラッグプロキシイメージやイメージの特性を指定できます。ドラッグプロキシの指定例については、例:ドラッグプロキシの指定を参照してください。
ドラッグプロキシがいずれかのコントロール上に移動すると、dragEnter イベントが生成されます。コントロールをドロップターゲットとするには、dragEnter イベントに対するハンドラを次のように定義する必要があります。イベントハンドラは、通常、次のアクションを実行します。
dragEnter イベントのイベントオブジェクトの action プロパティの値は、コピーを行う場合も DragManager.MOVE です。これは、コピーであることを示す Ctrl キーが押されたことをドロップターゲットが認識する前に、dragEnter イベントが発生するからです。
Flex では、リストコントロールの dragOver イベントのデフォルトのイベントハンドラが、action プロパティを自動的に設定します。非リストコントロールの場合、またはリストコントロールの dragOver イベントを明示的に処理する場合は、DragManager.showFeedback() メソッドを使用して、action プロパティをドラッグ操作のタイプを示す値、つまり DragManager.COPY、DragManager.LINK、DragManager.MOVE または DragManager.NONE に設定します。dragOver イベントの詳細については、例:ドロップターゲットの dragOver イベントおよび dragExit イベントの処理を参照してください。
dragDrop イベントは、dragEnter イベントハンドラがドロップを受け付けるために DragManager.acceptDragDrop() メソッドを呼び出した後に、ユーザーがマウスボタンを離してデータをターゲットにドロップすると発生します。このイベントに対するハンドラを定義して、ドラッグデータをドロップターゲットに追加する必要があります。
イベントハンドラは、DragSource.dataForFormat() メソッドを使用してドラッグデータを取得します。前の例では、ドラッグデータにドロップターゲットの新しい背景色が格納されています。この場合、イベントハンドラは setStyle() を呼び出して、ドロップターゲットの背景色を設定します。
リストコントロールの dragEnabled または dropEnabled プロパティを true に設定すると、Flex ではドラッグ&ドロップイベントのデフォルトのイベントハンドラが自動的に定義されます。これらのデフォルトのイベントハンドラを使用するか(アプリケーションで余分な作業が発生しません)、または独自のイベントハンドラを定義できます。
リストコントロールでイベントハンドラを使用する、一般的なシナリオが 3 つあります。
デフォルトのイベントハンドラを使用する
ドラッグイニシエータの dragEnabled を true に設定、またはドロップターゲットの dropEnabled を true に設定すると、すべてのドラッグ&ドロップイベントの移動は Flex によって処理されます。必要な作業は、ドラッグ&ドロップ操作の一環としてデータをコピーする場合に、独自の dragDrop イベントハンドラを定義することだけです。詳細については、データの移動とコピーを参照してください。
独自のイベントハンドラを定義する
リストコントロールのドラッグ&ドロップ操作を制御する場合は、任意のコンポーネントに対してできるように、ドラッグ&ドロップイベントを明示的に処理できます。このシナリオでは、ドラッグイニシエータで dragEnabled プロパティを false に設定するか、またはドロップターゲットで dropEnabled を false に設定します。これらのイベントの処理の詳細については、例:非リストコントロールでの単純なドラッグ&ドロップ操作を参照してください。
独自のイベントハンドラを定義し、デフォルトのイベントハンドラを使用する
ドラッグ&ドロップイベントに対して独自のイベントハンドラを追加し、同時にビルドインのドラッグ&ドロップハンドラを使用することもできます。この場合、まず独自のイベントハンドラが実行され、次に Flex のデフォルトのイベントハンドラが実行されます。何らかの理由により、デフォルトのイベントハンドラを明示的に実行できなくするには、独自のイベントハンドラ内から Event.preventDefault() メソッドを呼び出します。
Tree コントロールが受け付けるデータは構造体であるので、Tree コントロールでは、他のリストコントロールとは異なる方法でドラッグ&ドロップを処理します。Tree コントロールでは、dragDrop イベントのイベントハンドラは、同じ Tree コントロール内でのデータの移動またはコピー、または他の Tree コントロールへのデータのコピーを行う際のアクションのみを実行します。ある Tree コントロールからデータをドラッグし、他の Tree コントロール上にそのデータをドロップして移動する場合、dragDrop イベントのイベントハンドラではなく、dragComplete イベントのイベントハンドラが、実際にはデータをターゲット Tree コントロールに追加する作業を行います。ソース Tree コントロールからデータを削除する作業についても同じです。これは、移動データのリペアレントには、最初にソース Tree コントロールからのデータの削除が必要となるためです。
したがって、dragDrop イベントまたは dragComplete イベントのイベントハンドラで Event.preventDefault() を呼び出す場合は、ドロップビヘイビアを自分自身で実装する必要があります。詳細については、例:非リストコントロールでのデータの移動とコピーを参照してください。
次の例は、例:非リストコントロールでのデータの移動とコピーのセクションの例を変更したもので、ある DataGrid コントロールから別の DataGrid コントロールにドラッグされたデータにアクセスする dragDrop イベントのイベントハンドラを定義しています。このイベントハンドラは、dragDrop イベントのデフォルトのイベントハンドラよりも先に実行され、ドラッグイニシエータからドロップターゲットにドラッグされた DataGrid の各行の「Artist」フィールドを Alert コントロール内に表示します。
<?xml version="1.0"?>
<!-- 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:Application>
前の例で実行する SWF ファイルは以下のとおりです。
dataForFormat() メソッドの指定する引数の値が "items" であることに注意してください。これは、リストコントロールでは、ドラッグデータのデータフォーマットに対して事前に定義された値があるからです。Tree コントロール以外のすべてのリストコントロールでは、フォーマットストリングは「items」です。Tree コントロールの場合、フォーマットストリングは「treeItems」です。
また、dataForFormat() メソッドの戻り値が配列であることにも注意してください。dataForFormat() メソッドは、1 つのアイテムのみをドラッグしている場合でも、リストコントロールに対しては常に配列を返します。これは、リストコントロールでは、複数のアイテムを選択できるからです。
このページに新しいコメントが追加された場合に、電子メールでの通知を希望する。 | コメントレポート