Vbox/Hbox 什么时候给它的 children 分配坐标?

When does Vbox/Hbox assign coordinate for it's children?

我在单击时将矩形放在 vbox 上,然后打印矩形的坐标。在按下键时,我只打印坐标。查看此示例代码示例:

@FXML
private VBox vbox;

@FXML
private AnchorPane anchorpane;

private List<Rectangle> rectangles = new ArrayList<>();

@Override
public void initialize(URL location, ResourceBundle resources) {
    System.out.println("init");

}

@FXML
private void onMouseClick(MouseEvent e) {
    System.out.println("click");
    vbox.getChildren().clear();

    for(int i = 0; i < 3 ; i++){
        Rectangle r = new Rectangle(100.0, 10.0, Color.BLACK);
        r.addEventHandler(KeyEvent.ANY, this::onKeyTyped);
        rectangles.add(r);
        vbox.getChildren().add(r);

        System.out.println(" r Yposition :" + r.getLayoutY() + " or " + r.getBoundsInParent().getMinY() + " or " + r.getBoundsInLocal().getMinY());
        System.out.println("Vbox height : " + vbox.getBoundsInLocal().getHeight());

    }

}

@FXML
private void onKeyTyped(KeyEvent e) {
    System.out.println("Key pressed");
    for (Rectangle r : rectangles){         
        System.out.println(" r Yposition :" + r.getLayoutY() + " or " + r.getBoundsInParent().getMinY() + " or " + r.getBoundsInLocal().getMinY());
        }
    System.out.println("Vbox height : " + vbox.getBoundsInLocal().getHeight());
}

这给我以下输出:

click
r Yposition :0.0 or 0.0 or 0.0
Vbox height : 10.0
r Yposition :0.0 or 0.0 or 0.0
Vbox height : 10.0
 r Yposition :0.0 or 0.0 or 0.0
Vbox height : 10.0

Key pressed
 r Yposition :0.0 or 0.0 or 0.0
 r Yposition :10.0 or 10.0 or 0.0
 r Yposition :20.0 or 20.0 or 0.0
Vbox height : 30.0

所以我想 JavaFX 在屏幕上打印时会分配形状的坐标。但是刷新时如何在Vbox中获得形状的坐标?

将矩形添加到 VBox 后,如果立即调用 getBoundsInParent(),则不会得到任何结果。

可以找到原因here:

Layout and CSS are also tied to pulse events. Numerous changes in the scene graph could lead to multiple layout or CSS updates, which could seriously degrade performance. The system automatically performs a CSS and layout pass once per pulse to avoid performance degradation. Application developers can also manually trigger layout passes as needed to take measurements prior to a pulse.

所以如果你真的需要在同一遍中这些矩形的边界,你可以调用:

vbox.layout();

在将每个矩形添加到框中以获得其最终位置之后。

根据 Javadoc,layout():

Executes a top-down layout pass on the scene graph under this parent. Calling this method while the Parent is doing layout is a no-op

现在这将如您所愿地工作:

for(int i = 0; i < 3 ; i++){
    Rectangle r = new Rectangle(100.0, 10.0, Color.BLACK);
    rectangles.add(r);
    vbox.getChildren().add(r);
    vbox.layout();

    System.out.println(" r Yposition :" + r.getLayoutY() + " or " + r.getBoundsInParent().getMinY() + " or " + r.getBoundsInLocal().getMinY());
    System.out.println("Vbox height : " + vbox.getBoundsInLocal().getHeight());
}

或者,您可以重写 vboxlayoutChildren() 方法,因为它在布局传递期间被调用以在该父级中布置子级:

private VBox vbox=new VBox(){

    @Override
    protected void layoutChildren() {
        super.layoutChildren(); 
        for (Rectangle r : rectangles){         
            System.out.println(" r Yposition :" + r.getLayoutY() + " or " + r.getBoundsInParent().getMinY() + " or " + r.getBoundsInLocal().getMinY());
        }
    }

};

它会给你同样的结果。请注意,这不适用于添加到 FXML 文件的 vbox,因为您需要为其创建一个新实例。