在java fx行的中间添加一个节点

时间:2018-11-15 20:45:20

标签: javafx

我有一条线,我希望将一个正方形的文本放置在此行的中间。

我使用堆栈窗格创建了带有文本的正方形。这条线是可拖动的,因此我希望正方形在被拖动时保持在该线的中间。

我尝试过:

weightSquare.layoutXProperty().bind((line.startXProperty().add(line.endXProperty())).divide(2).add(line.translateXProperty()));
weightSquare.layoutYProperty().bind((line.startYProperty().add(line.endYProperty())).divide(2).add(line.translateXProperty()));

其中weightSquare是包含矩形和文本的StackPane。

当前,weightSquare在该行的中间附近,但在中间并不完美。当线绕重物移动时,正方形会保持在线中间附近,但有时会稍微偏离线。

我想要这样的东西:

Example of what I want

谢谢。

1 个答案:

答案 0 :(得分:1)

假设没有对行或StackPane进行任何变换,则可以根据这样的行属性来计算StackPane的位置

stackPane.layoutX = (line.startX + line.endX - stackPane.width) / 2;

(对y坐标进行相应处理。)

transformXtransformY可以简单地添加,但是常规转换将要求您

  1. 听变换的变化
  2. 在行的开始/结束坐标上使用localToParent,以获取父级中的位置。

我建议使用Bindings.createDoubleBindings来使双绑定复杂化,因为这样会使计算值的公式更易于阅读。

示例

我使用Label,因为它也提供了背景/边框功能。

@Override
public void start(Stage primaryStage) throws IOException {
    Label label = new Label();
    label.setStyle("-fx-background-color: white; -fx-border-color: black;");
    label.setPadding(new Insets(2, 4, 2, 4));

    Line line = new Line(300, 300, 300, 100);

    label.layoutXProperty().bind(Bindings.createDoubleBinding(
            () -> (line.getStartX() + line.getEndX() - label.getWidth()) / 2,
            line.startXProperty(), line.endXProperty(), label.widthProperty()));
    label.layoutYProperty().bind(Bindings.createDoubleBinding(
            () -> (line.getStartY() + line.getEndY() - label.getHeight()) / 2,
            line.startYProperty(), line.endYProperty(), label.heightProperty()));

    DoubleProperty angle = new SimpleDoubleProperty();
    line.endXProperty().bind(Bindings.createDoubleBinding(() -> 300 + 200 * Math.sin(angle.get()), angle));
    line.endYProperty().bind(Bindings.createDoubleBinding(() -> 300 + 200 * Math.cos(angle.get()), angle));

    Timeline timeline = new Timeline(
            new KeyFrame(Duration.ZERO, new KeyValue(angle, 0d, Interpolator.LINEAR)),
            new KeyFrame(Duration.seconds(10), new KeyValue(angle, Math.PI * 2, Interpolator.LINEAR)));
    timeline.setCycleCount(Animation.INDEFINITE);
    label.textProperty().bind(timeline.currentTimeProperty().asString());
    timeline.play();

    Scene scene = new Scene(new Pane(line, label), 600, 600);

    primaryStage.setScene(scene);
    primaryStage.show();
}