2016-12-05 7 views
1

ドラッグ&ドロップで要素を並べ替えることができるリストビューを持っていますが、2つのデフォルトアイコンを独自のカスタムアイコンに置き換えたい。 ListCell自体またはその親の両方でsetCursor(Cursor.HAND)setCursor(new ImageCursor(image))を試してみましたが、ドラッグ中に何も反映されません。誰でもこれについてどうやって行くのか知っていますか?ドラッグアンドドロップ中にJavaFx ListViewのカーソルを変更する

Edit1:この質問は、並べ替え可能なリストビューを作成する方法とは関係ありません。これは、リストビュー項目のドラッグアンドドロップ時にデフォルトのカーソルを変更する方法です。 drag-n-drop時には、同じデフォルトのカーソルアイコンもあるので、
How to create a reorder-able TableView in JavaFxの複製ではありません。

EDIT2:は、WindowsとLinuxのOSに影響を与えます。

screenshot drag-n-drop not allowed icon

screenshot drag-n-drop allowed icon

package sample; 

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.SnapshotParameters; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.image.WritableImage; 
import javafx.scene.input.*; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 

public class Main extends Application { 

    @Override 
    public void start(Stage stage) throws Exception{ 

     Pane pane = new Pane(); 
     ObservableList<String> items = FXCollections.observableArrayList("test1", "test2", "test3", "test4"); 
     ListView<String> lw = new ListView<>(); 
     lw.setCellFactory(param -> new MyListCell()); 
     lw.setItems(items); 
     pane.getChildren().add(lw); 
     stage.setTitle("RearrangeListView"); 
     stage.setScene(new Scene(pane, 300, 150)); 
     stage.show(); 
    } 

    private class MyListCell extends ListCell<String> { 

     public MyListCell() { 

      setOnDragDetected(event -> { 

       if (getItem() == null) { 
        return; 
       } 

       if (event.getButton() == MouseButton.PRIMARY) { 
        WritableImage image = snapshot(new SnapshotParameters(), null); 
        Dragboard dragboard = startDragAndDrop(TransferMode.MOVE); 
        ClipboardContent content = new ClipboardContent(); 
        content.putString("abc"); 
        dragboard.setDragView(image); 
        dragboard.setContent(content); 
        //setCursor(Cursor.HAND); 
        event.consume(); 
       } 
      }); 

      setOnDragOver(event -> { 
       if (event.getGestureSource() != this && event.getDragboard().hasString()) { 
        event.acceptTransferModes(TransferMode.MOVE); 
       } 
       event.consume(); 
      }); 

      setOnDragEntered(event -> { 
       if (event.getGestureSource() != this && event.getDragboard().hasString()) { 
        setOpacity(0.3); 
       } 
      }); 

      setOnDragExited(event -> { 
       if (event.getGestureSource() != this && event.getDragboard().hasString()) { 
        setOpacity(1); 
       } 
      }); 

      setOnDragDropped(event -> { 
       if (getItem() == null) { 
        return; 
       } 

       Dragboard db = event.getDragboard(); 
       boolean success = false; 

       if (db.hasString()) { 

        ObservableList<String> items = getListView().getItems(); 
        String source = ((MyListCell) event.getGestureSource()).getItem(); 
        String target = ((MyListCell) event.getGestureTarget()).getItem(); 

        int sourceIdx = items.indexOf(source); 
        int targetIdx = items.indexOf(target); 

        //swap 
        items.set(sourceIdx, target); 
        items.set(targetIdx, source); 

        success = true; 
       } 

       event.setDropCompleted(success); 
       event.consume(); 
      }); 

      setOnDragDone(DragEvent::consume); 
     } 

     @Override 
     protected void updateItem(String item, boolean empty) { 
      super.updateItem(item, empty); 

      if (empty || item == null) { 
       setText(null); 
      } else { 
       setText(item); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

@ jewelseaこの質問は、並べ替え可能なリストビューを作成する方法とは関係ありません。これは、リストビュー項目のドラッグアンドドロップ時にデフォルトのカーソルを変更する方法です。 – jbilander

+0

@ jewelseaありがとう、しかし、私はあなたの例を試して、それはドラッグ時に同じデフォルトのカーソル(下のボックスのポインタ)に苦しんでいます。このスクリーンショットを見てください。[link](https://dl.dropboxusercontent.com/u/60356891/screenshot_reorder_origami.png)そのカーソルは私が変更しようとしているものです。 – jbilander

答えて

0

OK ES私の調査結果によると、ないのMac OS Xの、私は今、私の誤解を理解すると思います。 JavaFXはDragViewとCursorの両方をサポートし、同時にそれらを表示します。だから私はあなたが求めていると思うものは、DragViewまたはDragViewとカスタムカーソルの両方を表示する方法です。次のように変更して、How to create a reorder-able TableView in JavaFx:これを行うには

一つの方法は、への回答を変更することである

private ImageCursor dragCursor; 
. . . 
// inside start() 
dragCursor = new ImageCursor(
    new Image(
     "https://cdn2.iconfinder.com/data/icons/web/512/Cursor-512.png", 
     32, 32, true, true 
    ) 
); 
// at the end of setOnDragDetected() 
getScene().setCursor(dragCursor); 
// change setOnDragDone() to: 
setOnDragDone(event -> { 
    event.consume(); 
    getScene().setCursor(Cursor.DEFAULT); 
}); 

あなたは何のカーソルではなく、カスタムの画像にカーソルを希望しない場合は、あなただけ呼び出すことができます。

getScene().setCursor(Cursor.NONE); 

私はOS Xでこのプログラムをテストしましたが、そこではうまくいきました。あなたの走行距離は異なる場合があります。カーソル操作はオペレーティングシステムによって異なる場合があることに注意してください(たとえば、この回答が変更されていない場合、OS Xではドラッグすると、Windowsで表示されているボックスでカーソルが表示されません。 DragViewイメージに加えて)。

上記の変更は、シーン内のオブジェクトをドラッグしている限り機能しているようです。ステージの外にドラッグすると、カーソルはデフォルトのカーソルに戻ります(JavaFXはカーソルがシーンの外を通過するとカーソルの制御を許可しないため、カーソルが修正されません)。

+1

ありがとう、私はこれを私のMac上で今テストしましたが、OS Xでは動作しますがLinuxやWindowsでは動作しません。何らかの形でこれらのOSはカスタムカーソルを独自のデフォルトカーソルで上書きするようです。本当に迷惑だけど、私はそれと一緒に生きなければならないと思う。 – jbilander

関連する問題