JavaFX-强制GridPane的子代适合单元格的大小 [英] JavaFX - force the child of a GridPane to fit the size of the cell

查看:167
本文介绍了JavaFX-强制GridPane的子代适合单元格的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图强制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的大小发生变化时动态调整单元格的大小,可以向其widthPropertyheightProperty添加监听器,如下所示:

@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);

或者...

如果您希望使用ColumnConstraintsRowConstraints来确定单元格大小,则可以设置Pane进行扩展,并且仅在监听器中更新其片段,该监听器现在可以监听ColumnConstraints:

If you wish to use ColumnConstraints and RowConstraints to determine the cell size you can set the Panes 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆