首页 文章

如何在JavaFX 8中按事件位置拖动鼠标时获取Node?

提问于
浏览
1

我创建了代码示例:

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

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

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

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

1 回答

  • 2

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

    • 通过在 onDragDetected 事件中为源节点调用 startFullDrag 来使用 MouseDragEvent .

    • mouseTransparent 设置为 true ,以允许JavaFX将 MouseEvent 传送到 target 圈而不是 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);
    

相关问题