java - JavaFX - 强制 GridPane 的子级适应单元格的大小
问题描述
我试图强制 a 的子GridPane
元素适应它所在的单元格的大小。在这种情况下,我正在创建一个月视图日历,并且列和行是一个设定大小,而不管其中有什么。
在此日历上,每个单元格都包含一个普通单元格,每个单元格VBox
都VBox
包含一个标签,该标签显示当月中的某天以及该天的每个事件。许多日子没有事件;其中一些有一个事件;还有一些有不止一个事件。
日历大小取决于窗口大小,并且会根据窗口大小而增长和缩小。现在,如果单元格太小而无法容纳所有事件,那么该VBox
单元格中当天的高度会大于单元格。
标题行具有以下约束:
HEADER_CONSTRAINT = new RowConstraints(10, -1, 500,
Priority.NEVER, VPos.BASELINE, true);
和其他行有这个约束:
ROW_CONSTRAINT = new RowConstraints(30, 30, Integer.MAX_VALUE,
Priority.ALWAYS, VPos.TOP, true);
我认为我需要做的是:
grid.add(cell, c, r);
vbox.maxHeightProperty().bind(grid.getRow(r).heightProperty()); // <-- this line is not right, but something like this.
解决方案
正如@fabian 正确提到的那样, a 的大小VBox
完全取决于其子项的大小。如果您希望拥有一个不根据其子项调整大小的容器,您可以使用 aPane
代替。像这样:
public void start(Stage primaryStage)
{
GridPane root = new GridPane();
Scene scene = new Scene(root, 300, 300);
int c = 0, r = 0;
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
root.add(c0, c, r);
primaryStage.setScene(scene);
primaryStage.show();
}
添加要测试的形状:
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
{
Circle circle = new Circle(160, Color.BLUE);
circle.setCenterX(160);
circle.setCenterY(160);
c0.getChildren().add(circle);
}
root.add(c0, c, r);
请注意,虽然形状突出到 的边界之外c0
,但边界c0
保持在原位,表明其大小不受影响。为了防止内容突出,您需要添加一个剪辑:
c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));
如果你想要一个更花哨的剪辑而不是简单的修剪,例如淡入、淡出和阴影,你可以在这里阅读这个非常好的教程。
现在只需将 this 替换Circle
为 your VBox
,以便 theVBox
是 this 的子级Pane
,然后将 the 添加Pane
到 your 中GridPane
就完成了。我将在这里提供我的最终代码作为参考:
public void start(Stage primaryStage)
{
GridPane root = new GridPane();
Scene scene = new Scene(root, 300, 300);
int c = 0, r = 0;
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
{
Circle circle = new Circle(160, Color.BLUE);
circle.setCenterX(160);
circle.setCenterY(160);
c0.getChildren().add(circle);
}
root.add(c0, c, r);
primaryStage.setScene(scene);
primaryStage.show();
}
更新:
@Jai 指出在这个实现中大小是静态的。如果您希望在单元格大小发生GridPane
变化时动态调整单元格的大小,您可以为其添加一个侦听器widthProperty
,heightProperty
如下所示:
int rowCount = 5, columnCount = 7; // You should know these values.
ChangeListener<Number> updater = (o, oV, nV) ->
{
double newWidth = root.getWidth() / columnCount;
double newHeight = root.getHeight() / rowCount;
root.getChildren().forEach(n ->
{
// Assuming every child is a Pane.
Pane p = (Pane) n;
p.setPrefSize(newWidth, newHeight);
p.setClip(new Rectangle(newWidth, newHeight));
});
};
root.widthProperty().addListener(updater);
root.heightProperty().addListener(updater);
或者...
如果您希望使用ColumnConstraints
andRowConstraints
来确定单元格大小,您可以将Pane
s 设置为展开,并且仅在侦听器中更新它们的剪辑,现在侦听器会侦听ColumnConstraints
and RowConstraints
:
ColumnConstraints cc = new ColumnConstraints(200);
RowConstraints rc = new RowConstraints(200);
c0.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
c0.setClip(new Rectangle(cc.getPrefWidth(), rc.getPrefHeight()));
和...
ChangeListener<Number> updater = (o, oV, nV) ->
{
root.getChildren().forEach(n ->
{
// Assuming every child is a Pane.
Pane p = (Pane) n;
p.setClip(new Rectangle(cc.getPrefWidth(), rc.getPrefHeight()));
});
};
cc.prefWidthProperty().addListener(updater);
rc.prefHeightProperty().addListener(updater);
推荐阅读
- c# - 为什么我在 LookUpEdit 中得到“System.Data.DataRowView”
- android - 如何将播放器置于顶部位置
- javascript - javascript函数中的第二个括号是什么意思?用例是什么?
- python - 比较 2 个数据框中的行并计算相似列的数量
- ajax - 如何让 Googlebot 抓取从 AJAX 加载的内容,但阻止它索引 URL 命中?
- javascript - 从数组创建地图,按字段分组。Javascript。洛达什
- blockchain - 如何获取已明确授予多链地址的所有权限的列表
- mysql - 从多个列中选择但检索列名
- android - 使用新的 Google Jetpack 组件的最低 Android API 级别是多少
- chromium - 为什么在像 STB 这样的嵌入式系统上,钴在 Youtube 中的性能比铬好得多?