JavaFX - 强制GridPane的子项适合单元格的大小
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaFX - 强制GridPane的子项适合单元格的大小相关的知识,希望对你有一定的参考价值。
我试图强迫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正确提到的那样,VBox
的大小完全取决于其子女的大小。如果您希望容器根据其子容器不调整大小,则可以使用Pane
。像这样:
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()));
如果你想要一个更精美的剪辑而不是简单的剪裁,比如淡入,淡出和阴影,你可以阅读这个非常好的教程here。
现在只需用你的Circle
替换这个VBox
,以便VBox
是这个Pane
的孩子,并将Pane
添加到你的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
和RowConstraints
来确定单元格大小,你可以设置Pane
s进行扩展,只更新它们在监听器中的剪辑,现在监听ColumnConstraints
和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);
以上是关于JavaFX - 强制GridPane的子项适合单元格的大小的主要内容,如果未能解决你的问题,请参考以下文章
JavaFX:GridPane 中的 ComboBox 导致不必要的大小调整