0

I'm attempting to make a node that I've created draggable.

I'm able to place the nodes at the point that I like in the pane, but when it comes to dragging them around, they just seem to be automatically offput.

I've tried making a Delta class that would just contain an x and y which would be updated accordingly during the pressing of the mouse on the node.

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

The node itself is defined by the class 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);
    }
}

I'm confused as to why this would affect the position of the node when dragged?

enter image description here

Orange Receptacle
  • 1,173
  • 3
  • 19
  • 40

1 Answers1

0

You forgot to take the mouse position into account when it's pressed.

You've got the following equation

mousePosition - mousePressedPosition = targetPosition - startPosition

so dragDelta should be

startPosition - mousePressedPosition = targetPosition - mousePosition

Personally I prefer using the coordinate system of the parent, but using scene coordinates should work too, unless you've got some transformations in place, that are not just translations.

Example

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();
}
fabian
  • 80,457
  • 12
  • 86
  • 114