The JavaFX Drag and Drop support enables you to design your JavaFX applications so that users can drag JavaFX nodes (controls) onto other JavaFX nodes and have your application be able to listen for, and react to these drag-and-drop events. Drag and drop can be useful as a way for users to specify actions more easily, in the situations where that makes sense - e.g dragging files to new locations, or data to analytics operations etc.

By the way, the JavaFX Drag and Drop support is quite similar to the HTML5 Drag and Drop support. If you already know HTML5 drag and drop functionality (via JavaScript) it will be easier to understand how JavaFX Drag and Drop functionality works. If not - just start directly with JavaFX Drag and Drop support.

Drop Source and Drop Target

The JavaFX Drag and Drop support divides JavaFX controls involved in drag and drop into the categories drag sources and drop targets .

A drag source is a JavaFX control (e.g. a 2D shape, ImageView etc.) which can be dragged onto another node. In general, most JavaFX controls can be used as drag sources.

A drop target is a JavaFX control onto which you can drag and then drop a drag source. When the drag source is dropped onto the drop target an event is fired which your application can listen for and respond to.

JavaFX Drag and Drop Example

Here is a JavaFX drag and drop example showing how to make one 2D circle into a drag source, and another 2D circle into a drop target:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class DragAndDropExample extends Application {

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

    public void start(Stage primaryStage) {

        Circle circle = createCircle("#ff00ff", "#ff88ff",100);

        circle.setOnDragDetected((MouseEvent event) -> {
            System.out.println("Circle 1 drag detected");

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

            ClipboardContent content = new ClipboardContent();
            content.putString("Circle source text");
            db.setContent(content);
        });
        circle.setOnMouseDragged((MouseEvent event) -> {
            event.setDragDetect(true);
        });

        Circle circle2 = createCircle("#00ffff", "#88ffff",300);

        circle2.setOnDragOver(new EventHandler<DragEvent>() {
            public void handle(DragEvent event) {
                if (event.getGestureSource() != circle2 && event.getDragboard().hasString()) {
                    event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                }

                event.consume();
            }
        });

        circle2.setOnDragDropped((DragEvent event) -> {
            Dragboard db = event.getDragboard();
            if (db.hasString()) {
                System.out.println("Dropped: " + db.getString());
                event.setDropCompleted(true);
            } else {
                event.setDropCompleted(false);
            }
            event.consume();
        });

        Pane pane = new Pane();
        pane.getChildren().add(circle);
        pane.getChildren().add(circle2);

        Scene scene = new Scene(pane, 1024, 800, true);
        primaryStage.setScene(scene);
        primaryStage.setTitle("2D Example");

        primaryStage.show();
    }

    private Circle createCircle(String strokeColor, String fillColor, double x) {
        Circle circle = new Circle();
        circle.setCenterX(x);
        circle.setCenterY(200);
        circle.setRadius(50);
        circle.setStroke(Color.valueOf(strokeColor));
        circle.setStrokeWidth(5);
        circle.setFill(Color.valueOf(fillColor));
        return circle;
    }
}