设置 Column/Row 后 JavaFX GridPane 节点边界不正确

JavaFX GridPane Incorrect Node Bounds After Setting Column/Row

设置 GridPane 中包含的节点的新行和列位置时,边界直到稍后才会更新(我的猜测是 JavaFX 在循环结束时计算这些)。我想知道是否有一种方法可以强制重新计算这些边界,以便 boundsAfter 包含正确的值而不是与 boundsPre 相同(如输出所示)?

Bounds boundsPre = theNode.localToScene(theNode.getBoundsInLocal());
System.out.println("PRE-MOVE: " + boundsPre);

GridPane.setColumnIndex(theNode, newCol);
GridPane.setRowIndex(theNode, newRow);
// Todo: Force JavaFX to recalculate the bounds here

Bounds boundsAfter = theNode.localToScene(theNode.getBoundsInLocal());
System.out.println("BOUNDS: " + boundsAfter );

输出:

PRE-MOVE: BoundingBox [minX:25.0, minY:339.0, minZ:0.0, width:243.0, height:116.0, depth:0.0, maxX:268.0, maxY:455.0, maxZ:0.0]
BOUNDS: BoundingBox [minX:25.0, minY:339.0, minZ:0.0, width:243.0, height:116.0, depth:0.0, maxX:268.0, maxY:455.0, maxZ:0.0]

解决方案 1

设置行或列位置后,在基础窗格上调用layout()方法。根据 Oracle JavaFX 文档,这“在此父项 下的场景图上执行自上而下的布局传递”,这导致重新计算属于的所有子节点的边界窗格。

Bounds boundsPre = theNode.localToScene(theNode.getBoundsInLocal());
System.out.println("PRE-MOVE: " + boundsPre);

GridPane.setColumnIndex(theNode, newCol);
GridPane.setRowIndex(theNode, newRow);

baseLayout.layout(); // Causes a layout pass which updates the bounds

Bounds boundsAfter = theNode.localToScene(theNode.getBoundsInLocal());
System.out.println("BOUNDS: " + boundsAfter );

输出:

PRE-MOVE: BoundingBox [minX:25.0, minY:87.0, minZ:0.0, width:243.0, height:116.0, depth:0.0, maxX:268.0, maxY:203.0, maxZ:0.0]
BOUNDS: BoundingBox [minX:25.0, minY:213.0, minZ:0.0, width:243.0, height:116.0, depth:0.0, maxX:268.0, maxY:329.0, maxZ:0.0]

解决方案 2

如果您不想立即更新边界,请观察 boundsInLocal 属性。此事件将在 JavaFX 完成其下一个布局过程时触发。

theNode.boundsInLocalProperty().addListener((observableValue, bounds, updatedBounds) ->
{
    System.out.println("BOUNDS: " + updatedBounds);
});

信用

正如 Slaw 在问题评论中指出的那样:

So either observe the boundsInLocal property and react when it changes, or call applyCss() followed by layout() on the root of the scene. The first approach is likely "cleaner"