在JavaFX 8中如何通过事件位置拖动鼠标来获取Node?

时间:2018-12-03 07:59:30

标签: java javafx javafx-8 mouseevent

我已经创建了代码示例:

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());
    }
}

在这里,我只是添加两个圆圈,我想通过简单地从一个圆圈拖动到另一个圆圈将它们连接到一条直线上。但是问题是我要在从源圆拖动鼠标时验证鼠标是否进入目标圆。输入后,我只想将线的端点绑定到目标圆的中心点,或者如果没有输入除源一以外的任何圆,则在鼠标释放时删除线。

不幸的是,当拖动一个圆圈到另一个圆圈时,没有捕捉到鼠标事件。但是有可能获得鼠标在场景中的位置。我试图通过简单地存储所有圈子(我有很多,超过10K),每次迭代并检查circle.contains(me.getSceneX(), me.getSceneY())来解决此问题。在我看来,这似乎有点昂贵,或者喜欢发明滚轮。

有一个问题,在JavaFX 8中是否可以通过使用内置的JavaFX功能以适当的方式根据场景位置获取节点?

1 个答案:

答案 0 :(得分:2)

You need to modify the code a bit:

  • Use MouseDragEvents by calling startFullDrag for the source node in the onDragDetected event.
  • Set mouseTransparent to true for the line to allow JavaFX to deliver the MouseEvents to the target circle instead of the Line.
  • Modify the event handlers to yield different results, if the mouse was released on the target circle.
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);
相关问题