ドキュメント



JavaFX: イベントの処理

7 ドラッグ・アンド・ドロップ操作

このドキュメントでは、JavaFXアプリケーションにドラッグ・アンド・ドロップ機能を実装する方法、ドラッグ・アンド・ドロップ・ジェスチャに関連するオブジェクト、転送可能なデータの型、およびドラッグ・アンド・ドロップ・ジェスチャの実行時に発生するイベントについて説明します。

また、このドキュメントでは、使用されているAPIおよび説明で取り上げられているマテリアルを例示するコード・サンプルも紹介します。

ドラッグ・アンド・ドロップ操作の対象となるオブジェクトおよびデータ型

ドラッグ・アンド・ドロップ操作とは、2つのオブジェクト(ジェスチャ・ソースおよびジェスチャ・ターゲット)間のデータ転送のことです。次のオブジェクトがジェスチャ・ソースおよびジェスチャ・ターゲットになります。

  • ノード

  • シーン

ジェスチャ・ソースおよびジェスチャ・ターゲットは、両方が単一のJavaFXアプリケーションに属していても、2つの異なるJavaFXアプリケーションまたはJavaクライアント・アプリケーションに属していてもかまいません。さらに、JavaFXアプリケーションとサード・パーティ(ネイティブ)アプリケーション(Windows Explorerやデスクトップなど)との間にドラッグ・アンド・ドロップを実装することもできます。

ドラッグ・アンド・ドロップ・ジェスチャは、「ユーザーがジェスチャ・ソースでマウス・ボタンをクリックし、マウスをドラッグし、ジェスチャ・ターゲットでマウス・ボタンを放す」という動作です。ユーザーがデータをドラッグするときには、データのドロップ可否を示す視覚フィードバックが提供され、ドロップ可能な場所を認識するヒントとなります。

データはダッシュボードを使用して転送されます。このダッシュボードは、システム・クリップボードと同じインタフェースを持ちますが、ドラッグ・アンド・ドロップ・データ転送にのみ使用されます。

ドラッグ・アンド・ドロップ・ジェスチャでは、テキスト、イメージ、URL、ファイル、バイト、文字列など、様々なタイプのデータを転送できます。

javafx.scene.input.DragEventクラスは、ドラッグ・アンド・ドロップ・ジェスチャの実装に使用される基本クラスです。javafx.scene.inputパッケージ内の特定のメソッドおよびその他のクラスの詳細は、APIのドキュメントを参照してください。

転送モード

ジェスチャ・ソースとジェスチャ・ターゲットの間で実行される転送のタイプは、転送モードによって決まります。使用可能な転送モードは、COPYMOVEおよびLINKです。

ジェスチャ・ソースによりサポートされている転送モードが提示されます。ジェスチャ・ターゲットでは1つ以上の転送モードが受け入れられます。特定のドラッグ・アンド・ドロップ・ジェスチャで使用される転送モードは、ソースでサポートされていてターゲットで受け入れられるモードの中から、ユーザーが押したキーボード修飾子に基づいてシステムによって選択されます。

基本的なドラッグ・アンド・ドロップ・ジェスチャの実装

HelloDragAndDropサンプル・アプリケーションを使用して、基本的なドラッグ・アンド・ドロップ機能を実装する方法について説明します。例7-1に示すように、2つのテキスト・ノードがジェスチャ・ソースおよびジェスチャ・ターゲットとして定義されています。

例7-1

final Text source = new Text(50, 100, "DRAG ME");
final Text target = new Text(300, 100, "DROP HERE");

ソースでのドラッグ・アンド・ドロップ・ジェスチャの開始

ドラッグ・アンド・ドロップ・ジェスチャは、ジェスチャ・ソースに対してDRAG_DETECTEDイベントのハンドラ内からstartDragAndDropメソッドをコールすることによってのみ開始できます。ここでは、ジェスチャ・ソースでサポートされる転送モードを定義し、転送対象データをダッシュボード上に配置しています。

例7-2に、onDragDetectedハンドラの実装を示します。

例7-2

source.setOnDragDetected(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        /* drag was detected, start a drag-and-drop gesture*/
        /* allow any transfer mode */
        Dragboard db = source.startDragAndDrop(TransferMode.ANY);
        
        /* Put a string on a dragboard */
        ClipboardContent content = new ClipboardContent();
        content.putString(source.getText());
        db.setContent(content);
        
        event.consume();
    }
});

startDragAndDropメソッドには、ジェスチャ・ソースでサポートされる一連の転送モードを渡します。使用可能な転送モードを任意に組み合せて渡すことができます。TransferMode.COPYを渡した場合、ジェスチャ・ソースではコピーのみがサポートされ、移動と参照はサポートされません。

ターゲットでのDRAG_OVERイベントの処理

ドラッグ・アンド・ドロップ・ジェスチャが開始された後、データのドロップ先となるターゲット候補として任意のノードまたはシーン上にマウスがドラッグされます。DRAG_OVERイベント・ハンドラを実装することによって、データのドロップ先として許容するオブジェクトを指定します。

DRAG_OVERイベント・ハンドラの重要性に留意してください。ドラッグ・アンド・ドロップ操作が正常に実行されるようにするには、イベント発生時にacceptTransferModes(TransferMode...)メソッドをコールするDRAG_OVERイベント・ハンドラを実装し、ターゲットで受け入れられる転送モードをこのメソッドに渡す必要があります。渡した転送モードがいずれもジェスチャ・ソースでサポートされていない場合、ターゲット候補はそのドラッグ・アンド・ドロップ・ジェスチャに適していません。

イベントを受け入れるかどうかを判断する際には、ダッシュボード上にあるデータの型を考慮する必要があります。ダッシュボードに格納されているデータにアクセスするには、event.getDragboard()メソッドを使用します。

例7-3に、DRAG_OVERイベント・ハンドラの実装を示します。

例7-3

target.setOnDragOver(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
        /* data is dragged over the target */
        /* accept it only if it is not dragged from the same node 
         * and if it has a string data */
        if (event.getGestureSource() != target &&
                event.getDragboard().hasString()) {
            /* allow for moving */
            event.acceptTransferModes(TransferMode.MOVE);
        }
        
        event.consume();
    }
});

ジェスチャ・ターゲットでの視覚フィードバックの提供

ドラッグ・アンド・ドロップ・ジェスチャの実行時に、ユーザーがそのジェスチャに適したターゲット上にマウス・ポインタを置くと、ドロップ可能な場所を認識するヒントとして、一般にターゲットの外観が変更されます。

ドラッグ・ジェスチャがジェスチャ・ターゲット候補の境界に入ると、ターゲットにDRAG_ENTEREDイベントが送信されます。ドラッグ・ジェスチャがターゲット候補の境界から出ると、ターゲットにDRAG_EXITEDイベントが送信されます。ユーザーに視覚フィードバックを提供するには、DRAG_ENTEREDおよびDRAG_EXITEDイベント・ハンドラを使用してターゲットの外観を変更します。

例7-4に、視覚フィードバックとしてテキスト色の変更を実装する方法を示します。

例7-4

target.setOnDragEntered(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
    /* the drag-and-drop gesture entered the target */
    /* show to the user that it is an actual gesture target */
         if (event.getGestureSource() != target &&
                 event.getDragboard().hasString()) {
             target.setFill(Color.GREEN);
         }
                
         event.consume();
    }
});

ダッシュボードの内容検証の重要性に留意してください。ターゲットの外観が変更されるのは、ダッシュボードに適切な形式のデータ(この例では文字列)が含まれている場合のみです。

例7-5に、テキストの外観を元に戻すためのDRAG_EXITEDイベント・ハンドラの実装を示します。

例7-5

target.setOnDragExited(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
        /* mouse moved away, remove the graphical cues */
        target.setFill(Color.BLACK);

        event.consume();
    }
});

ターゲットでのDRAG_DROPPEDイベントの処理

ジェスチャ・ターゲットで前のDRAG_OVERイベントが受け入れられた後(ジェスチャ・ソースでサポートされている転送モードに対応している場合)、マウス・ボタンが放されると、DRAG_DROPPEDイベントがジェスチャ・ターゲットに送信されます。DRAG_DROPPEDイベント・ハンドラでは、イベント発生時にsetDropCompleted(Boolean)メソッドをコールしてドラッグ・アンド・ドロップ・ジェスチャを完了する必要があります。そうしないと、ジェスチャは失敗とみなされます。

例7-6に、DRAG_DROPPEDイベント・ハンドラの実装を示します。

例7-6

target.setOnDragDropped(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
        /* data dropped */
        /* if there is a string data on dragboard, read it and use it */
        Dragboard db = event.getDragboard();
        boolean success = false;
        if (db.hasString()) {
           target.setText(db.getString());
           success = true;
        }
        /* let the source know whether the string was successfully 
         * transferred and used */
        event.setDropCompleted(success);
        
        event.consume();
     }
});

ソースでのDRAG_DONEイベントの処理

ドラッグ・アンド・ドロップ・ジェスチャが完了したら、ジェスチャの完了状況を通知するためにジェスチャ・ソースにDRAG_DONEイベントが送信されます。DRAG_DONEイベント・ハンドラでは、イベント発生時にgetTransferModeメソッドをコールして転送モードを取得します。転送モードがNULLの場合は、データ転送が実行されなかったことを意味しています。例7-7に示すように、モードがMOVEの場合は、ジェスチャ・ソース上のデータがクリアされます。

例7-7

source.setOnDragDone(new EventHandler<DragEvent>() {
    public void handle(DragEvent event) {
        /* the drag and drop gesture ended */
        /* if the data was successfully moved, clear it */
        if (event.getTransferMode() == TransferMode.MOVE) {
            source.setText("");
        }
        event.consume();
    }
});

カスタム・データのドラッグ

同様に、カスタム・データに対するドラッグ・アンド・ドロップ・ジェスチャを実装できます。例7-8に示すように、カスタム・データ型を定義します。

例7-8

/** The custom format */
private static final DataFormat customFormat =
    new DataFormat("helloworld.custom");

カスタム・データをダッシュボード上に配置する場合は、そのデータ型を指定します。データはシリアライズ可能である必要があります。

ダッシュボードからデータを読み取るときには、適切なキャスティングが必要になります。

アプリケーション・ファイル

ソース・コード 

NetBeansプロジェクト 

ウィンドウを閉じる

目次

JavaFX: イベントの処理

展開 | 縮小