How to draw arrow JavaFX? (pane)

I need to make a directed graph from undirected I can draw line edge, but I don't know how to make arrows:

public class Edge extends Group {

protected Cell source;
protected Cell target;

Line line;

public Edge(Cell source,Cell target) {

    this.source = source;
    this.target = target;

    source.addCellChild(target);
    target.addCellParent(source);

    line = new Line();

    line.startXproperty().bind(source.layoutXproperty().add(source.getBoundsInParent().getWidth() / 2.0));
    line.startYproperty().bind(source.layoutYproperty().add(source.getBoundsInParent().getHeight() / 2.0));

    line.endXproperty().bind(target.layoutXproperty().add( target.getBoundsInParent().getWidth() / 2.0));
    line.endYproperty().bind(target.layoutYproperty().add( target.getBoundsInParent().getHeight() / 2.0));

   getChildren().addAll(line);
}

Solution

You need to add 2 more lines to make the arrow (or the polygon filling the arrow has the same points)

Note that the direction of the arrow can be determined based on the difference between the beginning and end of the line end of the "main" connection One end of each line constituting the arrow needs to be in the same coordinates as the end of the main line The other end can be calculated by combining a part of the main line direction and a part orthogonal to the main line:

public class Arrow extends Group {

    private final Line line;

    public Arrow() {
        this(new Line(),new Line(),new Line());
    }

    private static final double arrowLength = 20;
    private static final double arrowWidth = 7;

    private Arrow(Line line,Line arrow1,Line arrow2) {
        super(line,arrow1,arrow2);
        this.line = line;
        InvalidationListener updater = o -> {
            double ex = getEndX();
            double ey = getEndY();
            double sx = getStartX();
            double sy = getStartY();

            arrow1.setEndX(ex);
            arrow1.setEndY(ey);
            arrow2.setEndX(ex);
            arrow2.setEndY(ey);

            if (ex == sx && ey == sy) {
                // arrow parts of length 0
                arrow1.setStartX(ex);
                arrow1.setStartY(ey);
                arrow2.setStartX(ex);
                arrow2.setStartY(ey);
            } else {
                double factor = arrowLength / Math.hypot(sx-ex,sy-ey);
                double factorO = arrowWidth / Math.hypot(sx-ex,sy-ey);

                // part in direction of main line
                double dx = (sx - ex) * factor;
                double dy = (sy - ey) * factor;

                // part ortogonal to main line
                double ox = (sx - ex) * factorO;
                double oy = (sy - ey) * factorO;

                arrow1.setStartX(ex + dx - oy);
                arrow1.setStartY(ey + dy + ox);
                arrow2.setStartX(ex + dx + oy);
                arrow2.setStartY(ey + dy - ox);
            }
        };

        // add updater to properties
        startXproperty().addListener(updater);
        startYproperty().addListener(updater);
        endXproperty().addListener(updater);
        endYproperty().addListener(updater);
        updater.invalidated(null);
    }

    // start/end properties

    public final void setStartX(double value) {
        line.setStartX(value);
    }

    public final double getStartX() {
        return line.getStartX();
    }

    public final DoubleProperty startXproperty() {
        return line.startXproperty();
    }

    public final void setStartY(double value) {
        line.setStartY(value);
    }

    public final double getStartY() {
        return line.getStartY();
    }

    public final DoubleProperty startYproperty() {
        return line.startYproperty();
    }

    public final void setEndX(double value) {
        line.setEndX(value);
    }

    public final double getEndX() {
        return line.getEndX();
    }

    public final DoubleProperty endXproperty() {
        return line.endXproperty();
    }

    public final void setEndY(double value) {
        line.setEndY(value);
    }

    public final double getEndY() {
        return line.getEndY();
    }

    public final DoubleProperty endYproperty() {
        return line.endYproperty();
    }

}

use

@Override
public void start(Stage primaryStage) {
    Pane root = new Pane();
    Arrow arrow = new Arrow();
    root.getChildren().add(arrow);

    root.setOnMouseClicked(evt -> {
        switch (evt.getButton()) {
            case PRIMARY:
                // set pos of end with arrow head
                arrow.setEndX(evt.getX());
                arrow.setEndY(evt.getY());
                break;
            case SECONDARY:
                // set pos of end without arrow head
                arrow.setStartX(evt.getX());
                arrow.setStartY(evt.getY());
                break;
        }
    });

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

    primaryStage.setScene(scene);
    primaryStage.show();
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>