JavaFX-强制GridPane的子代适合单元格的大小 [英] JavaFX - force the child of a GridPane to fit the size of the cell
问题描述
我试图强制GridPane
的子项适合其所在单元格的大小.在这种情况下,我将创建一个月视图日历,并且列和行都是设置的大小,而不管什么是在里面.
I am trying to force the child of a GridPane
to fit the size of the cell it is in. In this case, I am creating a month view calendar and the columns and rows are a set size regardless of what is in it.
在此日历上,每个单元格都包含一个普通的VBox
,每个VBox
都包含一个标签,该标签显示该月的某天以及该日的每个事件.许多日子里没有活动.其中一些有一个事件;还有一些有多个活动.
On this calendar, each cell contains a normal VBox
and each VBox
contains a label that displays the day of the month and each of the events for that day. Many of the days have no events; some of them have one event; and a few have more than one event.
日历大小取决于窗口大小,并且会根据窗口大小而增加和缩小.现在,如果该单元格太小而无法容纳所有事件,则该单元格中当天的那个VBox
的高度会变得大于该单元格.
The calendar size is dependent on the window size and will grow and shrink in accordance to the window. Right now, if the cell is too small to fit all of the events, then the height of that one VBox
for that day in the cell becomes larger than the cell.
标题行具有以下约束:
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
代替.像这样:
As @fabian mentioned correctly, the size of a VBox
is entirely dependent the sizes of its children. If you wish to have a container that does not resize depending on its children, you can use a Pane
instead. Like this:
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
的边界仍保留在原处,表明其大小不受影响.为了防止内容突出,您需要添加一个剪辑:
Note that although the shape protrudes outside of the bounds of c0
, the borders of c0
stay in place, indicating that its size is unaffected. To prevent the content from protruding out, you need to add a clip:
c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));
如果您想要更精美的剪辑而不是简单的修剪(例如淡入,淡出和阴影),则可以阅读此非常好的教程
If you want a more fancy clip instead of a simple trim, such as fade-in, fade-out, and shadows, you can read this very good tutorial here.
现在只需将Circle
替换为VBox
,以使VBox
是此Pane
的子代,然后将Pane
添加到您的GridPane
中就可以了.我将在此处提供我的最终代码作为参考:
Now just replace this Circle
with your VBox
, so that the VBox
is a child of this Pane
, and add the Pane
to your GridPane
and you're done. I will provide my final code here as a reference:
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
添加监听器,如下所示:
@Jai pointed out that the size is static in this implementation. If you wish to dynamically adjust the size of the cells if the size of the GridPane
changes, you can add a listener to its widthProperty
and heightProperty
like this:
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
进行扩展,并且仅在监听器中更新其片段,该监听器现在可以监听ColumnConstraints
和
If you wish to use ColumnConstraints
and RowConstraints
to determine the cell size you can set the Pane
s to expand, and only update their clips in the listener, which now listens to 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);
这篇关于JavaFX-强制GridPane的子代适合单元格的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!