如何绘制箭头JavaFX?(窗格) [英] How to draw arrow JavaFX? (pane)

查看:43
本文介绍了如何绘制箭头JavaFX?(窗格)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从无向图制作有向图.我可以画线边缘,但我不知道如何制作箭头:

I need to make directed graph from undirected. I can draw line-Edge, but I don't know how to make arrow:

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

推荐答案

你需要再添加 2 条线来制作一个箭头(或一个 Polygon 与填充箭头相同的点).

You need to add 2 more lines to make an arrow head (or a Polygon with the same points for a filled arrow head).

请注意,箭头的方向可以根据主"连接的线端的起点和终点之间的差异来确定.组成箭头的每条线的一端需要与主线的末端处于相同的坐标.另一端可以通过组合主线方向的一部分和与主线正交的部分来计算:

Note that the direction of the arrow can be determined based on the difference between start and end of the line ends of the "main" connection. One end of each of the lines that make up the arrow head need to be at the same coordinates as the end of the main line. The other end can be calculated by combining a part in direction of the main line and a part ortogonal 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();
    }

}

使用

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

这篇关于如何绘制箭头JavaFX?(窗格)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆