質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Q&A

解決済

2回答

2195閲覧

JavaFXでボタンコントロールのD&D

mugichon

総合スコア61

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

0グッド

0クリップ

投稿2017/04/15 07:00

###前提・実現したいこと
ここに質問したいことを詳細に書いてください
現在、JavaFXを使用しアプリケーションを作成しています。
同一コンテナ内でボタンコントロールをドラッグアンドドロップで移動させたいのですが、
コンテナに張り付いたままで、ドラッグ最中の動作(マウスカーソルに半透明のアイコンが付いてくるような)にもなりません。

ボタンコントロールをドラッグアンドドロップするにはどうしたらよいでしょうか?

###発生している問題・エラーメッセージ

特になし

###該当のソースコード

Java

1 //ドラッグ 2 dbutton.setOnDragDetected(new EventHandler<MouseEvent>() { 3 @Override 4 public void handle(MouseEvent event) { 5 System.out.println("ドラッグが開始されました。"); 6 Dragboard db = button.startDragAndDrop(TransferMode.MOVE); 7 ClipboardContent content = new ClipboardContent(); 8 content.put(DataFormat.RTF, dbutton); 9 db.setContent(content); 10 event.consume(); 11 } 12 }); 13 //D&Dされる側(同一コンテナ) 14 anchor.setOnDragOver(new EventHandler<DragEvent>() { 15 public void handle(DragEvent event) { 16 event.acceptTransferModes(TransferMode.COPY_OR_MOVE); 17 System.out.println("DragOver"); 18 event.consume(); 19 } 20 }); 21 anchor.setOnDragEntered(new EventHandler<DragEvent>() { 22 public void handle(DragEvent event) { 23 System.out.println("DragEntered"); 24 event.consume(); 25 } 26 }); 27 anchor.setOnDragExited(new EventHandler<DragEvent>() { 28 public void handle(DragEvent event) { 29 System.out.println("DragExited"); 30 event.consume(); 31 } 32 }); 33 anchor.setOnDragDropped(new EventHandler<DragEvent>() { 34 public void handle(DragEvent event) { 35 Dragboard db = event.getDragboard(); 36 boolean success = false; 37 if (db.hasString()) { 38 System.out.println("DragDropped"); 39 success = true; 40 } 41 event.setDropCompleted(success); 42 event.consume(); 43 } 44 }); 45 anchor.getChildren().add(dbutton);

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

気づいた点をコメントします。

  1. D&Dのdrag対象は?

setOnDragDetectedをdbuttonに対して行っているのでドラッグ対象はdbuttonになります。ハンドラーの中でbutton.startDragAndDrop(...)としていることから、質問者さんはbuttonをD&Dしようとしたのだと推測しますが、buttonに対してはsetOnDragDetectedハンドラーが設定されてませんのでD&Dは開始しません。

  1. clipboardの中身

ボタンを転送するのに用いるデータフォーマットにRTF(MIMEタイプ=text/rtf)を使っていますが、ボタンはRTFではないのでこれでは転送できません。一般にJavaオブジェクトを転送する場合、しかるべきデータフォーマット(=MIMEタイプ)でオブジェクトをシリアライズして転送し、受け取り側ではデータフォーマットを確認してデシリアライズすべきです。しかし本件の目的ではそのような面倒なことをせずともclipboardにダミーの文字列でも設定し、転送対象のButtonインスタンスは適当な場所に覚えておくというサボリ実装でも許容できると思います。ボタンだけではなくもっと多くの種類のデータをD&D対象にしたり、アプリケーション間でデータの転送をするには前述したようにきちんとつくる必要がありますが。

  1. 受け取り処理

onDragDroppedハンドラーの中でdb.hasStringを使っていますがこれはdb.putStringとした場合のみtrueになります。コードではput(DataFormat.RTF, ...)としてデータを設定したわけですからdb.hasStringはfalseになります。送り手側と受け手側でデータフォーマットが一致してないので転送はできないわけです。

なお、2.で述べたようなサボリ実装の例を挙げておきます。

java

1// FXMLを利用したコントローラを仮定 2class Controller implements Initializable { 3 @FXML AnchorPane anchor; 4 @FXML Button button1; 5 @FXML Butotn button2; 6 ... 7 @Override 8 public void initialize(URL location, ResourceBundle resources) { 9 ... 10 // D&Dの移動先のAnchorPaneとその上に乗っけている対象ノードを指定 11 new DnDController(anchor, button1, button2); 12 } 13} 14... 15class DnDController { 16 static final String DnDDummy = "drag and drop dummy"; 17 Node movingNode; // D&D対象ノード 18 19 DnDController(AnchorPane anchor, Button... dragSources) { 20 for (Button b : dragSources) { 21 b.setOnDragDetected(event -> { 22 System.out.println("start D&D"); 23 // 移動対象のノードをフィールドへ覚えておく 24 movingNode = (Node) event.getSource(); 25 Dragboard db = button.startDragAndDrop(TransferMode.MOVE); 26 ClipboardContent content = new ClipboardContent(); 27 content.putString(DnDDummy); // clipboardにはダミーを設定 28 db.setContent(content); 29 event.consume(); 30 }); 31 } 32 33 anchor.setOnDragDropped(event -> { 34 System.out.println("DragDropped"); 35 Dragboard db = event.getDragboard(); 36 boolean success = db.hasString() && db.getString().equals(DnDDummy); 37 if (success) { 38 // フィールドに覚えておいたノードをAnchorPaneのドロップ位置へ移動 39 AnchorPane.setLeftAnchor(movingNode, event.getX()); 40 AnchorPane.setTopAnchor(movingNode, event.getY()); 41 } 42 event.setDropCompleted(success); 43 event.consume(); 44 }); 45 46 // 他のハンドラーは質問者さんが書いた通りなので省略 47 anchor.setOnDragOver(event -> {...}); 48 anchor.setOnDragEntered(event -> {...}); 49 anchor.setOnDragExited(event -> {...}); 50 } 51}

(JavaFXをお使いなのでJava8前提であると推測しlambda構文を使用しています。)

投稿2017/04/15 09:13

編集2017/04/15 23:45
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mugichon

2017/04/15 21:20

ご教示いただきありがとうございます。 拙い質問内容にも関わらず的確なアドバイスありがとうございました。 おかげさまで無事D&Dすることができました! ただ、ドラッグのマウス移動中にボタンが半透明の状態にはなりませんが、 半透明状態でドラッグ移動中を表すようにするにはどのようにコーディングすれば良いでしょうか? なお、ドラッグ対象はご指摘の通りボタンで、同一AnchorPane内での移動となります。
KSwordOfHaste

2017/04/16 00:05

> ドラッグのマウス移動中にボタンが半透明の状態に そうした見栄えはJava標準ライブラリーがサポートしているD&Dの標準動作あるいはオプション動作にはなく、D&Dをサポートするアプリケーションがそれぞれこだわりの描画処理をやることで実現できるものだと思います。例えばD&D中にディスプレイ全体を覆うような透明なコンテナを作成し、そこにD&D中のボタンを不透明度(opacity)を下げて描画するといった少々面倒なことをすることになるだろうと思います。そうしたコードも調べながら書くことはできると思います。自分はそこまで凝ったことをやったことがありませんw;
mugichon

2017/04/16 22:57

ご回答いただきありがとうございます。 また、具体的な実装方法について言及いただきありがとうございます。 見栄えに関しては標準で無いんですね・・・ ちょっと難しそうですが、もう少しJavaFXに慣れたら試してみたいと思います。 ありがとうございました!
guest

0

D&Dに関してはご教示頂いた通りできましたので、一旦解決とさせていただきたいと思います。

投稿2017/04/16 22:57

mugichon

総合スコア61

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/04/16 23:13

うまくいってなによりです。ところで質問のクローズはベストアンサーを付けるか自己解決処理(自分で解決した方法をここへ回答する・・・のかな)とすると閲覧者は質問が解決したとわかりますよ~
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問