【问题标题】:JavaFX - draw line with arrow (Canvas)JavaFX - 用箭头画线(画布)
【发布时间】:2016-03-02 15:34:33
【问题描述】:

我无法将此代码重写为 JavaFX:

private final int ARR_SIZE = 8;

void drawArrow(Graphics g1, int x1, int y1, int x2, int y2) {
    Graphics2D g = (Graphics2D) g1.create();
    g.setPaint(Color.BLACK);

    double dx = x2 - x1, dy = y2 - y1;
    double angle = Math.atan2(dy, dx);
    int len = (int) Math.sqrt(dx * dx + dy * dy);
    AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
    at.concatenate(AffineTransform.getRotateInstance(angle));
    g.transform(at);

    g.drawLine(0, 0, len, 0);
    g.fillPolygon(new int[] { len, len - ARR_SIZE, len - ARR_SIZE, len }, new int[] { 0, -ARR_SIZE, ARR_SIZE, 0 },
            4);
}

我的解决方案无法正常工作,因为代码的结果:

drawArrow(gc, 200, 50, 50, 50);

.

预期结果是

.

private final int ARR_SIZE = 8;

void drawArrow(GraphicsContext gc, int x1, int y1, int x2, int y2) {

    gc.setFill(Color.BLACK);

    double dx = x2 - x1, dy = y2 - y1;
    double angle = Math.atan2(dy, dx);
    int len = (int) Math.sqrt(dx * dx + dy * dy);

    Affine affine = new Affine(Affine.translate(x1, y1));
    affine.createConcatenation(Affine.rotate(angle, 0, 0));
    gc.setTransform(affine);

    gc.strokeLine(0, 0, len, 0);
    gc.fillPolygon(new double[]{len, len - ARR_SIZE, len - ARR_SIZE, len}, new double[]{0, -ARR_SIZE, ARR_SIZE, 0},
            4);

}

你能帮我吗?

【问题讨论】:

  • 您必须更好地解释自己。什么不工作?你得到的结果有什么问题?您希望实现什么目标?
  • 嗨,预期结果是

标签: canvas javafx


【解决方案1】:

有两个原因:

  1. 按弧度而不是度数旋转:Transform.rotate 需要以度数为单位的角度(请参阅javadoc for Rotate constructorTransform.rotate 的 javadoc 在那里“重定向”),但 Math.atan2 返回弧度。
  2. Transform.createConcatenation 会创建一个新的Transform,而不是修改现有的Transform

这段代码应该可以工作:

void drawArrow(GraphicsContext gc, int x1, int y1, int x2, int y2) {
    gc.setFill(Color.BLACK);

    double dx = x2 - x1, dy = y2 - y1;
    double angle = Math.atan2(dy, dx);
    int len = (int) Math.sqrt(dx * dx + dy * dy);

    Transform transform = Transform.translate(x1, y1);
    transform = transform.createConcatenation(Transform.rotate(Math.toDegrees(angle), 0, 0));
    gc.setTransform(new Affine(transform));

    gc.strokeLine(0, 0, len, 0);
    gc.fillPolygon(new double[]{len, len - ARR_SIZE, len - ARR_SIZE, len}, new double[]{0, -ARR_SIZE, ARR_SIZE, 0},
            4);
}

【讨论】: