public class Example extends Application {
@Override
public void start(Stage stage) throws Exception {
Pane pane = new Pane();
Scene scene = new Scene(pane, 1000, 1000);
Circle circle = new Circle(400, 500, 50);
Rectangle rect = new Rectangle(200, 200, 20, 30);
Line line = new Line();
line.setStroke(Color.RED);
pane.getChildren().add(circle);
pane.getChildren().add(rect);
pane.getChildren().add(line);
Node[] nodes = {circle, rect};
scene.setOnMouseDragReleased(e -> {
System.out.println("Scene: drag released");
});
for (Node node:nodes) {
node.setOnDragDetected(e -> {
System.out.println("drag started");
line.setStartX(node.localToScene(node.getBoundsInLocal()).getCenterX());
line.setStartY(node.localToScene(node.getBoundsInLocal()).getCenterY());
line.setEndX(e.getX());
line.setEndY(e.getX());
node.startFullDrag();
});
node.setOnMouseDragged(e -> {
line.setEndX(e.getX());
line.setEndY(e.getY());
});
node.setOnMouseDragReleased(e -> {
System.out.println("Node: drag released");
line.setEndX((node.localToScene(node.getBoundsInLocal()).getCenterX()));
line.setEndY((node.localToScene(node.getBoundsInLocal()).getCenterX()));
});
stage.setScene(scene);
stage.show();
}
}
}
For some reason, drag release is called only for scene, but not for node. When line update in onMouseDragged for node is commented out, end of line doesn’t follow the cursor, but onMouseDragRelease is called for both scene and node.
I want to have smooth line drawing, but also preserve onMouseDragRelease particulary for the node.
>Solution :
From the documentation:
When you drag a node, it’s still under cursor, so it is considered being a potential gesture target during the whole gesture. If you need to drag a node to a different node and let the other node know about it, you need to ensure that the nodes under the dragged node are picked as the potential gesture targets. You can achieve this by calling setMouseTransparent(true) on the dragged node
In your case, the line is immediately under the mouse cursor (because you set the end coordinates of the line to the mouse coordinates during dragging), so the line receives the mouse drag released event.
Call
line.setMouseTransparent(true);
so that the node underneath can receive the event.
If you need the line to be able to receive mouse events at times other than the dragging, call
line.setMouseTransparent(true);
in the onDragDetected handler, and
line.setMouseTransparent(false);
in the onMouseDragReleased handler:
public class Example extends Application {
@Override
public void start(Stage stage) throws Exception {
Pane pane = new Pane();
Scene scene = new Scene(pane, 1000, 1000);
Circle circle = new Circle(400, 500, 50);
Rectangle rect = new Rectangle(200, 200, 20, 30);
Line line = new Line();
line.setStroke(Color.RED);
pane.getChildren().add(circle);
pane.getChildren().add(rect);
pane.getChildren().add(line);
Node[] nodes = {circle, rect};
scene.setOnMouseDragReleased(e -> {
System.out.println("Scene: drag released");
});
for (Node node:nodes) {
node.setOnDragDetected(e -> {
System.out.println("drag started");
line.setStartX(node.localToScene(node.getBoundsInLocal()).getCenterX());
line.setStartY(node.localToScene(node.getBoundsInLocal()).getCenterY());
line.setEndX(e.getX());
line.setEndY(e.getX());
line.setMouseTransparent(true);
node.startFullDrag();
});
node.setOnMouseDragged(e -> {
line.setEndX(e.getX());
line.setEndY(e.getY());
});
node.setOnMouseDragReleased(e -> {
System.out.println("Node: drag released");
line.setEndX((node.localToScene(node.getBoundsInLocal()).getCenterX()));
// Note you had a copy-and-paste error in the next line, which I have fixed:
line.setEndY((node.localToScene(node.getBoundsInLocal()).getCenterY()));
line.setMouseTransparent(false);
});
stage.setScene(scene);
stage.show();
}
}
}