设置 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"
设置 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"