I have created code example:
package stackoverflow;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class GetNodeByMousePositionWhileDragged extends Application {
private Line line;
private Group group = new Group();
@Override
public void start(Stage stage) throws Exception {
AnchorPane anchorPane = new AnchorPane();
Circle source = new Circle(30, Color.LIGHTGREEN);
source.setStroke(Color.BLACK);
source.setCenterX(100);
source.setCenterY(100);
source.setOnMousePressed(me -> {
me.consume();
drawLine(source, me);
});
source.setOnMouseDragged(me -> translateLineEnd(getPoint(me)));
source.setOnMouseReleased(event -> group.getChildren().remove(line));
Circle target = new Circle(30, Color.LIGHTBLUE);
target.setStroke(Color.BLACK);
target.setCenterX(400);
target.setCenterY(100);
target.setOnMousePressed(me -> {
me.consume();
drawLine(target, me);
});
target.setOnMouseDragged(me -> translateLineEnd(getPoint(me)));
target.setOnMouseReleased(event -> group.getChildren().remove(line));
group.getChildren().addAll(source, target);
anchorPane.getChildren().addAll(group);
stage.setScene(new Scene(anchorPane, 600, 400));
stage.setMaximized(true);
stage.show();
}
private void drawLine(Circle source, MouseEvent me) {
line = new Line();
line.setStroke(Color.BLACK);
line.setStrokeWidth(1);
line.startXProperty().bind(source.centerXProperty());
line.startYProperty().bind(source.centerYProperty());
translateLineEnd(getPoint(me));
group.getChildren().add(line);
}
private void translateLineEnd(Point2D point) {
line.setEndX(point.getX());
line.setEndY(point.getY());
}
private Point2D getPoint(MouseEvent me) {
return new Point2D(me.getSceneX(), me.getSceneY());
}
}
Here I am just adding two circles and I want to connect them with a line by simply dragging from one circle to another. But the problem is that I want to verify whether mouse entered target circle while I am dragging mouse from source circle. When it is entered I want just bind end points of the line to the target circle center points or remove line on mouse released if it is not entered any circle besides source one.
Unfortunately while dragging one circle another one is not catching mouseevents. But it is possible to get mouse position on scene. I tried to solve this problem by simply storing all circle (I have bunch of them, 10K+), iterating each time and checking circle.contains(me.getSceneX(), me.getSceneY())
. It seems to me a bit expensive way or like inventing wheel.
There is a question is it possible in JavaFX 8 to get node according scene position in proper way by using built-in JavaFX features?
You need to modify the code a bit:
MouseDragEvent
s by calling startFullDrag
for the source node in the onDragDetected
event.mouseTransparent
to true
for the line to allow JavaFX to deliver the MouseEvent
s to the target
circle instead of the Line
.private void drawLine(Circle source, MouseEvent me) {
line = new Line();
line.setMouseTransparent(true);
...
private Group group = new Group();
private boolean removeLine = true;
source.setOnMousePressed(me -> {
me.consume();
drawLine(source, me);
me.setDragDetect(true); // trigger dragDetected event immediately
});
source.setOnDragDetected(evt -> {
source.startFullDrag();
removeLine = true;
});
...
source.setOnMouseReleased(event -> {
if (removeLine) {
group.getChildren().remove(line);
}
});
target.setOnMouseDragReleased(me -> removeLine = false);