簡體   English   中英

JavaFX - 強制GridPane的子項適合單元格的大小

[英]JavaFX - force the child of a GridPane to fit the size of the cell

我試圖強制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();
}

SS1

添加要測試的形狀:

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

SS2

請注意,雖然形狀突出於c0的邊界之外,但是c0的邊界保持c0 ,表明其大小不受影響。 要防止內容突出,您需要添加剪輯:

c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));

SS3

如果你想要一個更精美的剪輯而不是簡單的剪裁,比如淡入,淡出和陰影,你可以在這里閱讀這個非常好的教程。

現在只需用你的VBox替換這個Circle ,這樣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的大小發生變化,你可以像這樣添加一個偵聽器到它的widthPropertyheightProperty

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設置為展開,並且僅在偵聽器中更新它們的剪輯,現在偵聽ColumnConstraintsRowConstraints

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM