今回は、Platform-supported drag-and-drop gestureについてみていきたいと思います。
Platform-supported drag-and-drop gestureは、アプリケーション間でデータを転送したいときに利用します。データの転送には、クリップボードを利用しますので、JavaFXのアプリケーションでないアプリケーションに対してデータを転送することもできます。
Platform-supported drag-and-drop gestureを開始するためには、DRAG_DETECTEDイベントで、startDragAndDropメソッドを呼び出します。このとき、Dragboardクラスのインスタンスが返されますので、ドラッグアンドドロップで転送したいデータを、ClipboardContentを利用して設定します。例えば、TextAreaの選択されているテキストの内容を転送したい場合は、DRAG_DETECTEDイベントで以下のようにします。
@Override public void handle(MouseEvent event) { TextArea source = (TextArea)event.getSource(); if (source.getSelectedText().isEmpty()) { return; } Dragboard board = source.startDragAndDrop(TransferMode.COPY_OR_MOVE); ClipboardContent content = new ClipboardContent(); content.putString(source.getSelectedText()); board.setContent(content); event.consume(); }
startDragAndDropメソッドを呼び出して、Dragboardに何も設定しない場合は、Platform-supported drag-and-drop gestureは開始されません。
Platform-supported drag-and-drop gestureが開始されると、DragEventが発生しますので、このイベントにハンドラを追加して、処理を行います。
DragEventのイベントタイプには、以下のものがあります。
- DRAG_DONE
- DRAG_DROPPED
- DRAG_ENTERED
- DRAG_ENTERED_TARGET
- DRAG_EXITED
- DRAG_EXITED_TARGET
- DRAG_OVER
基本的には、ドラッグ元でDRAG_DONEイベントにハンドラを追加し、ドラッグ先で残りのイベントにハンドラを追加します。DRAG_ENTERED_TARGETとDRAG_EXITED_TARGETについては、MouseEventやMouseDragEventのときと同様に、キャプチャリングフェーズあるいはバブリングフェーズでハンドラを追加したいときに利用します。
ドラッグ先では、DRAG_OVERイベントが発生したときに、Dragboardに設定されているデータを確認し、ドロップ対象とするかどうかの判定を、acceptTransferModesメソッドを呼び出すことによって行います。このメソッドの引数には、どのTransferModeでドロップするかを指定します。例えば、文字列のデータを移動させるためのドロップ対象とする場合は、DRAG_OVERイベントで以下のようにします。
@Override public void handle(DragEvent event) { Dragboard board = event.getDragboard(); if (board.hasString()) { event.acceptTransferModes(TransferMode.MOVE); } event.consume(); }
ドロップ対象とした場合、ドラッグ先のノード上でマウスをリリースすると、DRAG_DROPPEDイベントが発生しますので、このイベントにハンドラを追加して、ドロップしたときの処理を行います。
@Override public void handle(DragEvent event) { Dragboard board = event.getDragboard(); if (board.hasString()) { // ドロップ時の処理を実装 event.setDropCompleted(true); } event.consume(); }
ドロップの処理が正常に行われた場合は、DragEventのsetDropCompletedメソッドの引数にtrueを指定して呼び出しておきます。
ドロップが行われると、正常に終了したかどうかに関わらず、ドラッグ元にDRAG_DONEイベントが発生します。ドロップが正常に行われたかどうかは、DragEventのgetTransferModeメソッドで、TransferModeが取得できたかどうかで判断します。ドロップ対象ノード以外にドロップしたか、ESCでキャンセルされたか、setDropCompletedメソッドでfalseが設定された場合は、取得したTransferModeがNULLとなります。それ以外の場合は、ドロップされたときのTransferModeが取得されますので、取得したTransferModeの値に対する処理を行います。基本的には、TransferMode.MOVEを取得したときに、ドラッグしたデータを削除することになります。例えば、TextAreaの選択されているテキストの内容を転送していた場合に、TransferMode.MOVEでドロップした場合は、DRAG_DONEイベントで以下のようにします。
@Override public void handle(DragEvent event) { if (event.getTransferMode() == TransferMode.MOVE) { TextArea source = (TextArea)event.getSource(); source.deleteText(source.getSelection()); } event.consume(); }
ClipboardContentに設定できるデータは、DataFormatで定義されている以下のものがあります。
- FILES
- HTML
- IMAGE
- PLAIN_TEXT
- RTF
- URL
上記以外にも、DataFormatクラスのインスタンスを作成することによって、独自のデータを設定することもできます。ただし、設定するデータはシリアル化できるものである必要があります。
今回は、Platform-supported drag-and-drop gestureについて、どのようにして行うかをみていきました。次回は、これを利用したものを何か作ってみたいと思います。