JavaFX:制作可拖动节点时遇到问题

时间:2016-11-13 02:05:46

标签: java javafx

我正在尝试创建一个我已创建可拖动的节点。

我可以将节点放在窗格中我喜欢的位置,但是当它们拖动它们时,它们似乎只是自动输出。

我已经尝试制作一个只包含x和y的Delta类,在节点上按下鼠标时会相应地更新。

nfaPane.setOnMousePressed(event -> {
            if (!event.getButton().equals(MouseButton.PRIMARY)) return;
            for (final NFANode node : nfaNodes)
                if (node.isHover())
                    return;
            final NFANode nfaNode = new NFANode(nfaNodes.size(), event.getX(), event.getY());
            nfaPane.getChildren().add(nfaNode);
            nfaNodes.add(nfaNode);
            Delta dragDelta = new Delta();
            nfaNode.setOnMousePressed(event1 -> {
                dragDelta.setDragDeltaX(nfaNode.getLayoutX());
                dragDelta.setDragDeltaY(nfaNode.getLayoutY());
            });

            nfaNode.setOnMouseDragged(event1 -> {
                nfaNode.moveTo(event1.getSceneX() + dragDelta.getDragDeltaX(), event1.getSceneY() + dragDelta.getDragDeltaY());
            });
        });

节点本身由NFANode类定义:

package sample;

import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

/**
 * Created by David on 11/5/2016.
 */
public class NFANode extends Group {
    //private List<NFANode> next;
    public static final Font nfaFont = Font.font("Footlight MT Light", 25);
    private final Ellipse bubble;
    private final Text text;
    private double textWidth;

    public NFANode(int value, double x, double y) {
        this.text = new Text(x, y + 5, "");
        renumber(value);
        this.text.setFont(nfaFont);
        textWidth = this.text.getBoundsInLocal().getWidth();
        bubble = new Ellipse(x, y, this.text.getBoundsInLocal().getWidth() + 5, 25);
        this.text.setX(x - textWidth / 2);
        bubble.setStroke(Color.BLACK);
        bubble.setFill(Color.WHITE);
        getChildren().addAll(bubble, this.text);
    }

    public Text getText() {
        return text;
    }

    public void renumber(final int value) {
        final StringBuilder builder = new StringBuilder();
        for (char c : String.valueOf(value).toCharArray()) builder.append((char) (c + 8272));
        text.setText("Q" + builder.toString());
    }

    public void moveTo(final double x, final double y) {
        bubble.setCenterX(x);
        bubble.setCenterY(y);
        text.setX(x - textWidth / 2);
        text.setY(y + 5);
    }
}

我很困惑为什么这会在拖动时影响节点的位置?

enter image description here

1 个答案:

答案 0 :(得分:0)

按下鼠标时忘记了鼠标位置。

你有以下等式

mousePosition - mousePressedPosition = targetPosition - startPosition

所以dragDelta应该是

startPosition - mousePressedPosition = targetPosition - mousePosition

我个人更喜欢使用父级的坐标系,但是使用场景坐标也应该有效,除非你有一些转换,不仅仅是翻译。

示例

private static class Delta {

    private double dragDeltaX;
    private double dragDeltaY;

    public double getDragDeltaX() {
        return dragDeltaX;
    }

    public double getDragDeltaY() {
        return dragDeltaY;
    }

    public void setDragDelta(double x, double y) {
        this.dragDeltaX = x;
        this.dragDeltaY = y;
    }
}

@Override
public void start(Stage primaryStage) {
    Circle c = new Circle(30);
    c.setLayoutX(50);
    c.setLayoutY(50);

    Pane root = new Pane(c);

    Delta dragDelta = new Delta();

    c.setOnMousePressed(event1 -> {
        Point2D mouseInParent = c.localToParent(event1.getX(), event1.getY());
        dragDelta.setDragDelta(c.getLayoutX() - mouseInParent.getX(), c.getLayoutY()-mouseInParent.getY());
        event1.consume();
    });

    c.setOnMouseDragged(event1 -> {
        Point2D mouseInParent = c.localToParent(event1.getX(), event1.getY());
        c.setLayoutX(mouseInParent.getX() + dragDelta.getDragDeltaX());
        c.setLayoutY(mouseInParent.getY() + dragDelta.getDragDeltaY());
    });

    Scene scene = new Scene(root, 500, 500);

    primaryStage.setScene(scene);
    primaryStage.show();
}