4

JavaFX でドラッグ アンド ドロップを使用し、ドラッグされているアイテムを視覚的に確認できる機能を使用したいと考えています。実用的なソリューションと思われるものを実装しましたが、API に問題があるようです。

API によると、startDragAndDrop(TransferMode...) は setOnDragDetected 内で初期化する必要があります。これは、ドラッグボードを使用して、別のノードに転送したいコンテンツを保存する場所です。

編集:これは TrasferMode と関係があるようです。TransferMode.NONE を使用しても問題はありませんが、COPY、ANY、LINK を使用すると常にこの問題が発生します。

ただし、dragBoard.setContent(いくつかのクリップボード コンテンツ) を呼び出すと、マウスを使用した非常に小さな増分しか許可されません (任意の方向に最大 4 ピクセル!)。このコード行を削除すると、項目をドラッグしてどこにでもドラッグされるのを確認できますが、もちろん、クリップボードの内容を保存することはできません。

私が見る問題は、setOnMouseDragged(..) が setOnDragDetected! の前に呼び出されることです。setOnMouseDragged が setOnDragDetected の前に実行される理由はあまり意味がありません...

私のコードに、問題を引き起こしている可能性のある明らかなものはありますか? ドラッグ時に imgView の移動を確認し、通常どおりクリップボードのコンテンツとともにターゲットにドロップできるようにしたいだけです。

編集 2:以下のコードを更新して、ドラッグ イベントとマウス イベントではなく、ドラッグ イベントのみを使用するようにしました。両方を使用すると問題が発生します。まだ残っている問題は、setOnDragOver を使用するとドラッグされたノードが常にカーソルの真下になるため、ターゲットにドロップできないことです。

protected ImageView initImageView(Image img){

    final Pane ldzPane = GameBoard.getInstance().getLDZpane();

    final ObjectProperty<Point2D> dragAnchor = new SimpleObjectProperty<>();

    final ImageView imgView = new ImageView(img);

    final DoubleProperty initX = new SimpleDoubleProperty();
    final DoubleProperty initY = new SimpleDoubleProperty();

    final DoubleProperty dragX = new SimpleDoubleProperty();
    final DoubleProperty dragY = new SimpleDoubleProperty();

    final DoubleProperty newXPosition = new SimpleDoubleProperty();
    final DoubleProperty newYPosition = new SimpleDoubleProperty();

    final int buffer = 3;

    imgView.setOnDragDetected(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent event) {
            initX.set(imgView.getTranslateX());
            initY.set(imgView.getTranslateY());
            dragAnchor.set(new Point2D(event.getSceneX(), event.getSceneY()));
            ClipboardContent content = new ClipboardContent();
            content.putString(RHSIconizedToken.this.tokenLookupInfo());
            Dragboard db = imgView.startDragAndDrop(TransferMode.ANY); 
            db.setContent(content); 
            event.consume();
        }
    });

    imgView.setOnDragOver(new EventHandler<DragEvent>(){

        @Override
        public void handle(DragEvent event) {
            imgView.toFront();

            dragX.set(event.getSceneX() - dragAnchor.get().getX());
            dragY.set(event.getSceneY() - dragAnchor.get().getY());
            imgView.setOpacity(0.5);

            newXPosition.set(initX.get() + dragX.get());
            newYPosition.set(initY.get() + dragY.get());

            //if(       (Math.abs((newXPosition.get() - ldzPane.getWidth())) <=  ldzPane.getWidth() + startX + buffer) &&
            //      ((newXPosition.get() + startX + imgView.getImage().getWidth()+ buffer)<=  ldzPane.getWidth()))
                imgView.setTranslateX(newXPosition.get());

            //if(       (Math.abs((newYPosition.get() - ldzPane.getHeight())) <=  ldzPane.getHeight() + startY + buffer) &&
            //      ((newYPosition.get() + startY + imgView.getImage().getHeight()+ buffer)<=  ldzPane.getHeight()))
                imgView.setTranslateY(newYPosition.get());

            event.consume();
        }

    });

    imgView.setOnDragDone(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {

            LinkedList<RHSIconizedToken> iTokens = GameBoard.getInstance().getTokenBayItokens();
            if (event.getTransferMode() == TransferMode.MOVE) {
                RHSIconizedToken element = iTokens.remove(index);
                iTokens.add(index, new RHSIconizedToken(element.getImage(), new SourceToken("removed", "removed"), index));
                imgView.setVisible(false); 

                GameBoard theGameBoard = GameBoard.getInstance();
                GUI theGUI = GUI.getInstance();
                //was this the last one removed from the rhs?
                //if so we need to signal the CompileButton to be turned on!
                if(theGameBoard.isRHSempty())
                    theGUI.enableCompileButton();
                else
                    theGUI.disableCompileButton();
            }
            event.consume();
        }
    });

    imgView.setOnMouseEntered(new EventHandler <MouseEvent>() {
        public void handle(MouseEvent event) {
            imgView.setEffect(new Glow(0.5));
            event.consume();
        }
    });

    imgView.setOnMouseExited(new EventHandler <MouseEvent>() {
        public void handle(MouseEvent event) {
            imgView.setEffect(new Glow(0.0));
            imgView.setOpacity(1);
            event.consume();
        }
    });

    return imgView;
}
4

2 に答える 2

3

Java 8 では、視覚的なドラッグ アンド ドロップのサポートが強化されて出荷される予定です。DragBoard の setDragView (Image, XOffset, YOffset) メソッドはうまく機能し、Java 8 ベータ版で利用できます。

    imgView.setOnDragDetected(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent event) {
            ClipboardContent content = new ClipboardContent();
            content.putString(RHSIconizedToken.this.tokenLookupInfo());
            Dragboard db = imgView.startDragAndDrop(TransferMode.ANY);
            db.setDragView(image, 7, 7); 
            db.setContent(content); 
            event.consume();
        }
    });
于 2013-05-04T18:34:26.357 に答える