我可以强制 JavaFX 的 GridPane 平均分配空间吗?

Posted

技术标签:

【中文标题】我可以强制 JavaFX 的 GridPane 平均分配空间吗?【英文标题】:Can I force JavaFX's GridPane to distribute space evenly? 【发布时间】:2013-05-01 01:10:51 【问题描述】:

在 JavaFX 2 中使用 GirdPanes 时,我遇到了一些奇怪的布局行为。虽然它通常似乎在多个字段之间均匀分布水平空间,但在其他一些情况下却不会这样做。下面是一个展示效果的例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class TestDialog extends Stage 
    public TestDialog() 
        super();
        setTitle("Test");

        GridPane grid = new GridPane();
        grid.setHgap(5);
        grid.setVgap(5);
        grid.setPadding(new Insets(10, 10, 10, 10));

        final TextField tField1 = new TextField();
        final TextField tField2 = new TextField();
        tField2.setMaxWidth(200);

        grid.add(createLabel("Field 1:"), 0, 0);
        grid.add(tField1, 1, 0);
        grid.add(createLabel("Field 2:"), 2, 0);
        grid.add(tField2, 3, 0);

        Pane pane = new Pane();
//        pane.setMinSize(600, 100);  // first row has weird layout behaviour
        pane.setMinSize(100, 100); // first row is fine
        pane.setStyle("-fx-background-color: black");
        grid.add(pane, 0, 1, 4, 1);

        grid.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);

        setScene(new Scene(grid));
    

    private Label createLabel(String text) 
        Label label = new Label(text);
        label.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
        return label;
    

    public static void main(String[] args) 
        TestApplication.main(args);
    

    public static class TestApplication extends Application 
        @Override
        public void start(Stage stage) throws Exception 
            TestDialog dialog = new TestDialog();
            dialog.showAndWait();
        

        public static void main(String[] args) 
            launch(args);
        
    

在此示例中,如果按原样运行,对话框将很好地调整大小。如果额外窗格的最小大小更改为注释中的版本,那么事情就会出错:第一行中的额外空间将变成空白空间(而不是增加第一个字段),减少对话框大小需要它远离已经很小的第一个字段,保留空白区域。

有没有办法让 GridPane 实际使用第一个字段的可用水平空间?我知道将对话大小减小到所需的最小值以下并不一定会产生良好的结果,但首先不扩大该领域对我来说似乎是完全错误的。

我从 JDK 1.7.0_21 开始使用 JavaFX。

【问题讨论】:

【参考方案1】:

您必须查看 ColumnConstraints 和 RowConstraints 类。这些将告诉 GridPane 如何分配空间。不幸的是,这里的 API 有点尴尬。如果要均匀分配未知量的空间,则必须首先实例化一个约束,然后使用 #setPercentageWidth - 此选项在构造函数中不可用。

总而言之,具有 3 个均匀分布的列(如果可能,同时考虑最小尺寸)的 GridPane 将如下所示:

public class Test extends Application 
    public void start(final Stage stage) throws Exception 
        final GridPane grid = new GridPane();
        grid.getColumnConstraints().setAll(
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build(),
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build(),
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build()
        );
        grid.add(new Button("One"),0,0);
        grid.add(new Button("Two"),1,0);
        grid.add(new Button("and three"),2,0);

        stage.setScene(new Scene(grid));
        stage.show();
    

    public static void main(String[] args) 
        Application.launch(args);
    

您可以相应地处理 RowConstraints。您可能还想在单元格中设置对齐方式,以确保您的对话框在调整大小时仍然看起来不错。

【讨论】:

我知道这些限制,但到目前为止,我的实验都产生了有趣但不是很有用的结果。在存在最小尺寸的情况下,宽度的计算似乎完全被打破 - 如果所有列都设置为 25% 宽,则窗口会变得很大。我现在已经转到 MiG Layout。 ColumnConstraintsBuilder 已弃用。请参阅ColumnConstraints

以上是关于我可以强制 JavaFX 的 GridPane 平均分配空间吗?的主要内容,如果未能解决你的问题,请参考以下文章

可以决定 GridPane (JavaFX) 中的行数和列数

Javafx 中 GridPane 中的 HBox

JavaFX中GridPane的行居中对齐

JavaFX:将图像插入 GridPane

如何在 JavaFX 的 GridPane 中删除“幽灵线”?

JavaFX:如何从 GridPane 中动态创建的文本字段的值计算平均值?