Nick H
Nick H

Reputation: 227

JavaFX Drag and Drop a Shape on to Another Shape

I have a GridPane of Circles, and I want to be able to drag one circle on top of another and have the color from the first be applied to the second.

The problem I'm having is that I cannot get the target circle to detect a dragEntered or dragOver. I have been able to implement this successfully using Labels, but for some reason, a Circle does not give the same effect.

I have seen some quasi-solutions that involved setting circle.setMouseTransparent(true) so that the node under the dragged node can see the drag, but no luck here either.

Here's a link to the code that does a similar thing using Labels: Hello Drag and Drop

Here's an applicable snippet of my code:

              circle.setOnDragDetected(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {

                    Dragboard db = circle.startDragAndDrop(TransferMode.ANY);

                    System.out.print("Dragging...");
                    System.out.println("From row: " + draggedFromRow + " From col: " + draggedFromCol);

                    circle.setLayoutX(event.getSceneX());
                    circle.setLayoutY(event.getSceneY());


                    event.consume();
                }
            });

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

                public void handle(DragEvent event) {
                    System.out.println("onDragOver");

                    event.acceptTransferModes(TransferMode.ANY);

                    event.consume();
                }
            });


            circle.setOnDragDropped(new EventHandler<DragEvent>() {
                @Override
                public void handle(DragEvent event) {

                    int toCol = Integer.valueOf(circle.getId().substring(0, 1));
                    int toRow = Integer.valueOf(circle.getId().substring(1));

                    performSwap(draggedFromRow, draggedFromCol, toRow, toCol);

                    System.out.print("Dragg dropped on ");
                    System.out.println(toRow + " " + toCol);

                    event.consume();
                }
            });

            circle.setOnDragEntered(new EventHandler<DragEvent>() {
                public void handle(DragEvent event) {
                    System.out.println("drag entered!");

                    event.consume();
                }
            });


            circle.setOnDragExited(new EventHandler<DragEvent>() {
                public void handle(DragEvent event) {
                    System.out.println("drag left!");

                    event.consume();
                }
            });

Upvotes: 0

Views: 2201

Answers (1)

Nick H
Nick H

Reputation: 227

James_D had the correct answer to this problem in his comment above. Seems that even just to have the circle register that a drag and drop is occurring, you have to pass some data to a Dragboard (even if you don't want to pass data to the node).

This was added to my circle.setOnDragDetected method:

Dragboard db = circle.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(circle.getId());
db.setContent(content);

So the method now looks like this:

            circle.setOnDragDetected(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {

                    Dragboard db = circle.startDragAndDrop(TransferMode.ANY);
                    ClipboardContent content = new ClipboardContent();
                    content.putString(circle.getId());
                    db.setContent(content);

                    System.out.print("onDragDetected");

                    event.consume();
                }
            });

Upvotes: 1

Related Questions