我有这部分代码:
Group g = new Group();
double xMid = (end.getCenterX() - start.getCenterX())/2;
double yMid = (end.getCenterY() - start.getCenterY())/2;
Line a = new Line(xMid, yMid-4, xMid, yMid+4);
Line b = new Line(xMid, yMid-4, xMid-10, yMid);
Line c = new Line(xMid, yMid+4, xMid-10, yMid);
g.getChildren().add(a);
g.getChildren().add(b);
g.getChildren().add(c);
g.setRotate(getAngle(start, end));
g.setTranslateX(start.getCenterX());
g.setTranslateY(start.getCenterY());
以上代码负责在一行中间绘制一个箭头,该箭头从start
到end
(这些Circle
作为起点和终点) 。箭头必须以正确的方向旋转。这是带有这样箭头的多行的输出:
如您所见,如果角度接近±90°,则向左移动。
我read:
[...]如果转换和效果直接设置在这个孩子身上 分组,这些将包含在本集团的布局范围内。
但它并没有真正帮助我解决这个问题。您有任何想法如何解决这个问题吗?
答案 0 :(得分:1)
首先,形成三角形的3条线最容易使用Polygon
。
要修复基于布局边界选择的轴心点,您可以使用Rotate
转换和Translate
转换为transform
,或者只是计算2个矩阵的连接你自己的并使用Affine
:
private static final double[] POLYGON_POINTS = {
-5, -4,
-5, 4,
5, 0
};
private static void makeArrow(Pane parent, Circle start, Circle end, double t) {
Polygon arrow = new Polygon(POLYGON_POINTS);
arrow.setFill(null);
arrow.setStroke(Color.BLACK);
double dx = end.getCenterX() - start.getCenterX();
double dy = end.getCenterY() - start.getCenterY();
double d = Math.hypot(dx, dy);
double sin = dy / d;
double cos = dx / d;
// matrix:
// [ cos -sin 0 t * dx + start.getCenterX() ]
// [ sin cos 0 t * dy + start.getCenterY() ]
// [ 0 0 1 0 ]
// [ 0 0 0 1 ]
Affine affine = new Affine(cos, -sin, t * dx + start.getCenterX(), sin, cos, t * dy + start.getCenterY());
arrow.getTransforms().add(affine);
parent.getChildren().add(arrow);
}
@Override
public void start(Stage primaryStage) {
Circle end = new Circle(200, 20, 5);
Circle start = new Circle(20, 200, 5);
Line line = new Line(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY());
Pane root = new Pane(line, start, end);
makeArrow(root, start, end, 0.5);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
答案 1 :(得分:0)
我认为创建一个包含向上线和箭头的组更容易,然后只围绕中心旋转这个组。
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
Pane root = createPane();
root.setTranslateX(200);
root.setTranslateY(200);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
private Pane createPane() {
BorderPane root = new BorderPane();
ArrowFactory arrowfactory = new ArrowFactory();
double lineLength = 100;
double centerX = 0;
double centerY = 0;
root.getChildren().addAll(
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 0),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 30),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 45),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 60),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 90),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 135),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 180),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 225),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 270),
arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 315)
);
return root;
}
public static void main(String[] args) {
launch(args);
}
}
ArrayFactory.java
:
public class ArrowFactory {
private final int arrowWidth = 10;
private final int arrowHeight = 10;
public Group createLineAndArrow(double centerX, double centerY, double lineLength, double rotation) {
Group group = new Group();
Line line = new Line(centerX, centerY, centerX, centerY - lineLength);
Polygon upwardArrow = createUpwardArrow(centerX, centerY - lineLength / 2);
group.getChildren().addAll(line, upwardArrow);
group.getTransforms().add(new Rotate(rotation, centerX, centerY));
return group;
}
private Polygon createUpwardArrow(double centerX, double centerY) {
Polygon arrow = new Polygon(
createUpwardArrowPoints(centerX, centerY + arrowHeight/2));
arrow.setFill(Color.TRANSPARENT);
arrow.setStroke(Color.BLACK);
return arrow;
}
private double[] createUpwardArrowPoints(double centerX, double centerY) {
return new double[] {
centerX - arrowWidth / 2, centerY, // left
centerX + arrowWidth / 2, centerY, // right
centerX, centerY - arrowHeight, // top
};
}
}
使用圆心作为输入可以使用:
private Group createLineAndArrow(double x1, double y1, double x2, double y2) {
double distance = Math.hypot(x1-x2, y1-y2);
double angle = Math.toDegrees(Math.atan2(x2 - x1, y2 - y1));
return arrowfactory.createLineAndArrow(x1, y1, distance, angle);
}