java - JavaFX 8中如何在鼠标拖动事件位置时获取节点?

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

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

不幸的是,当拖动一个圆圈到另一个圆圈时,没有捕获鼠标事件。但可以获取场景上的鼠标位置。我尝试通过简单地存储所有圆(我有一堆,10K+),每次迭代并检查circle.contains(me.getSceneX(),me.getSceneY())来解决这个问题。在我看来,这有点昂贵,或者就像发明轮子一样。

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

最佳答案

您需要稍微修改一下代码:

  • 通过在 onDragDetected 事件中调用源节点的 startFullDrag 来使用 MouseDragEvent
  • 将该行的 mouseTransparent 设置为 true,以允许 JavaFX 将 MouseEvent 传递到 target 圆而不是线
  • 如果鼠标在目标圆圈上释放,请修改事件处理程序以产生不同的结果。
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);

关于java - JavaFX 8中如何在鼠标拖动事件位置时获取节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53589640/

相关文章:

java - 使用 javax.swing/javafx 列出文本区域中的系统属性

java - 为什么 JVM 在繁忙的自旋暂停后显示相同代码块的更多延迟?

java - 在具有 Java 正则表达式问题的组之间插入连字符

java - Ant 任务定义 OpenJDK 11 JavaFX SDK 11 Eclipse 2018-12

java - fedora 21 javafx 没有创建媒体播放器

java - 两个 ObservableDoubleValue 的最大值作为 ObservableDoubleValue

java - 如何更新 if block 中的实例变量?

java - 407 无法通过代理建立隧道

java - 添加新数据时无法刷新 TableView 单元格

java - 将皮肤应用于所有 JavaFX 子控件