如何使用 GridBagLayout

Note:

本课涵盖了手工编写布局代码,这可能会很困难。如果您不希望了解布局 管理 的所有详细信息,则可能更喜欢将GroupLayout布局 管理 器与构建器工具结合使用来布局 GUI。 NetBeans IDE是此类构建器工具之一。否则,如果您想手工编码并且不想使用GroupLayout,那么推荐使用GridBagLayout作为下一个最灵活,功能最强大的布局 管理 器。

如果您对使用 JavaFX 创建 GUI 感兴趣,请参阅在 JavaFX 中使用布局

这是使用GridBagLayout的示例的图片。

GridBagLayoutDemo 的快照

单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 GridBagLayoutDemo。另外,要自己编译和运行示例,请查阅example index

GridBagDemo 的代码在GridBagLayoutDemo.java中。

GridBagLayout是 Java 平台提供的最灵活(也是最复杂)的布局 管理 器之一。 GridBagLayout将组件放置在行和列的网格中,从而允许指定的组件跨越多个行或列。并非所有行都必须具有相同的高度。同样,并非所有列都必须具有相同的宽度。本质上,GridBagLayout将组件放置在网格中的矩形(单元)中,然后使用组件的首选大小来确定单元的大小。

下图显示了前面 Servlets 的网格。如您所见,网格具有三行三列。第二行中的按钮跨越所有列;第三行中的按钮跨越右两列。

GridBagLayoutDemo 及其网格的快照

如果您放大窗口,如下图所示,您将注意到包含 Button 5 的最下面一行获得了所有新的垂直空间。新的水平空间在所有列之间平均分配。调整大小的行为基于程序分配给GridBagLayout中各个组件的权重。您还将注意到,每个组件都占用了所有可用的水平空间,但是(如您通过按钮 5 可以看到的)没有占用所有可用的垂直空间。该行为也由程序指定。

用户放大后显示的 GridBagLayout。

程序指定其组件的尺寸和位置 Feature 的方式是通过为每个组件指定* constraints *。设置组件约束的首选方法是使用Container.add变体,将其传递给GridBagConstraints对象,如以下各节所示。

以下各节说明可以设置的约束并提供示例。

Specifying Constraints

以下代码是使用GridBagLayout的容器中的典型代码。在下一部分中,您将看到一个更详细的示例。

JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

//For each component to be added to this container:
//...Create the component...
//...Set instance variables in the GridBagConstraints instance...
pane.add(theComponent, c);

您可能从上面的示例中猜到了,即使多个组件具有不同的约束,也可以对多个组件重用相同的GridBagConstraints实例。但是,建议您不要重用GridBagConstraints,因为如果您忘记为每个新实例重置字段,这很容易导致引入细微的错误。

Note:

以下讨论假定GridBagLayout控制容器的组件方向为从左到右。

您可以设置以下GridBagConstraints个实例变量:

  • gridx , gridy

    • 在组件的左上方指定行和列。最左列的地址为gridx=0,最上一行的地址为gridy=0。使用GridBagConstraints.RELATIVE(默认值)可以指定将组件放置在刚添加到容器中的组件的右侧(对于gridx)或在其下方(对于gridy)。我们建议为每个组件指定gridxgridy值,而不仅仅是使用GridBagConstraints.RELATIVE;这往往会导致更可预测的布局。
  • gridwidth , gridheight

    • 在组件的显示区域中指定列数(对于gridwidth)或行数(对于gridheight)。这些约束指定组件使用的像元数,而不是指定使用的像素数。默认值为 1.使用GridBagConstraints.REMAINDER指定组件是其行(对于gridwidth)或列(对于gridheight)中的最后一个组件。使用GridBagConstraints.RELATIVE指定该组件是其行(对于gridwidth)或列(对于gridheight)中倒数第二个组件。我们建议为每个组件指定gridwidthgridheight值,而不是仅使用GridBagConstraints.RELATIVEGridBagConstraints.REMAINDER;这往往会导致更可预测的布局。

注意: GridBagLayout不允许组件跨越多行,除非该组件位于最左侧的列中,或者您已为该组件指定了gridxgridy的正值。

  • fill

    • 当组件的显示区域大于组件的请求大小时使用,以确定是否以及如何调整组件的大小。有效值(定义为GridBagConstraints常量)包括NONE(默认值),HORIZONTAL(使组件足够宽以水平填充其显示区域,但不改变其高度),VERTICAL(使组件足够高以垂直填充其显示区域) ,但不要更改其宽度)和BOTH(使组件完全填满其显示区域)。
  • ipadx , ipady

    • 指定内部填充:要添加到组件大小的数量。默认值为零。组件的宽度将至少为其最小宽度加上ipadx*2像素,因为填充适用于组件的两侧。同样,组件的高度将至少为其最小高度加ipady*2像素。
  • insets

    • 指定组件的外部填充-组件与其显示区域的边缘之间的最小距离。该值指定为Insets对象。默认情况下,每个组件都没有外部填充。
  • anchor

    • 当组件小于其显示区域时使用,以确定放置组件的位置(在该区域内)。有效值(定义为GridBagConstraints常量)是CENTER(默认值),PAGE_STARTPAGE_ENDLINE_STARTLINE_ENDFIRST_LINE_STARTFIRST_LINE_ENDLAST_LINE_ENDLAST_LINE_START

这是如何在具有默认的从左到右组件方向的容器中解释这些值的图片。

FIRST_LINE_STARTPAGE_STARTFIRST_LINE_END
LINE_STARTCENTERLINE_END
LAST_LINE_STARTPAGE_ENDLAST_LINE_END

Version note:

PAGE_**LINE_*常量在 1.4 中引入。以前的版本需要以罗盘点命名的值。例如,NORTHEAST表示显示区域的右上部分。我们建议您改用新的常量,因为它们使本地化更容易。

  • weightx , weighty

    • 指定权重是一门艺术,可能会对GridBagLayout控制的组件的外观产生重大影响。权重用于确定如何在列(weightx)和行(weighty)之间分配空间;这对于指定调整大小的行为很重要。

除非您为weightxweighty指定至少一个非零值,否则所有组件都将聚集在其容器的中央。这是因为当权重为 0.0(默认值)时,GridBagLayout会在其单元格网格和容器的边缘之间放置任何多余的空间。

通常,权重的极限值设置为 0.0 和 1.0:必要时使用中间的数字。较大的数字表示组件的行或列应获得更多空间。对于每一列,权重与该列中为组件指定的最高weightx有关,每个多列组件的权重均以某种方式在该组件所在的列之间分配。类似地,每一行的权重与为 a 所指定的最高weighty相关。该行中的组件。多余的空间倾向于流向最右边的列和最下面的行。

下一部分将在解释示例程序如何工作的上下文中深入讨论约束。

示例说明

这里还是 GridBagLayoutDemo 应用程序的图片。

GridBagLayoutDemo 的快照

单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 GridBagLayoutDemo。另外,要自己编译和运行示例,请查阅example index

以下代码创建GridBagLayout及其 管理 的组件。您可以在GridBagLayoutDemo.java中找到整个源文件。

JButton button;
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
                //natural height, maximum width
                c.fill = GridBagConstraints.HORIZONTAL;
}

button = new JButton("Button 1");
if (shouldWeightX) {
                   c.weightx = 0.5;
}
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Button 2");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Button 3");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 2;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Long-Named Button 4");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;      //make this component tall
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 1;
pane.add(button, c);

button = new JButton("5");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;       //reset to default
c.weighty = 1.0;   //request any extra vertical space
c.anchor = GridBagConstraints.PAGE_END; //bottom of space
c.insets = new Insets(10,0,0,0);  //top padding
c.gridx = 1;       //aligned with button 2
c.gridwidth = 2;   //2 columns wide
c.gridy = 2;       //third row
pane.add(button, c);

此示例对GridBagLayout管理 的所有组件使用一个GridBagConstraints实例,但是在实际情况下,建议您不要重用GridBagConstraints,因为如果您忘记为每个字段重置字段,很容易导致引入细微的错误。新实例。在将每个组件添加到容器之前,代码会在GridBagConstraints对象中设置(或重置为默认值)适当的实例变量。然后,它将组件添加到其容器中,并指定GridBagConstraints对象作为add方法的第二个参数。

例如,使按钮 4 更高,该示例具有以下代码:

c.ipady = 40;

在设置下一个组件的约束之前,代码会将ipady的值重置为默认值:

c.ipady = 0;

如果组件的显示区域大于组件本身,则可以使用GridBagConstraints.anchor约束来指定组件在显示区域中的下落。 anchor约束的值可以是绝对值(北,南,东,西等),也可以是相对方向的(在页面开头,行尾,第一行开头,等等),或者相对于组件的基准。有关anchor约束的可能值的完整列表(包括相对于基线的值),请参阅GridBagConstraints.anchor的 API 文档。您可以在上面的代码摘录中看到,按钮 5 通过将锚点设置为GridBagConstraints.PAGE_END来指定应将其显示在显示区域的末尾。

Note:

本教程的示例用于以不同的方式指定约束对象,您也可能在其他程序中看到这种方式。我们的示例未使用add方法指定约束,而是在GridBagLayout对象上调用setConstraints方法。例如:

GridBagLayout gridbag = new GridBagLayout();
pane.setLayout(gridbag);
...
gridbag.setConstraints(button, c);
pane.add(button);

但是,我们建议您使用Container.add方法,因为与使用setConstraints相比,它使代码更简洁。

下表显示了 GridBagLayoutDemo 的内容窗格中每个组件的所有约束。并非默认值的标记为**。与上一个表条目中的值不同的值以斜体标记。

ComponentConstraints
All componentsipadx = 0

fill = GridBagConstraints.HORIZONTAL
按钮 1ipady = 0 weightx = 0.5 weighty = 0.0 gridwidth = 1 anchor = GridBagConstraints.CENTER insets = new Insets(0,0,0,0) gridx = 0 gridy = 0
按钮 2weightx = 0.5
gridx = 1
网格= 0
按钮 3weightx = 0.5
gridx = 2
网格= 0
按钮 4ipady = 40
权重= 0.0
网格宽度= 3
gridx = 0
网格= 1
按钮 5ipady = 0
权重= 0.0
权重= 1.0
锚= GridBagConstraints.PAGE_END
插入=新插入(10,0,0,0)
网格宽度= 2
gridx = 1
网格= 2

GridBagLayoutDemo 具有跨越多个列的两个组件(按钮 4 和 5)。为了提高按钮 4 的高度,我们在其中添加了内部填充(ipady)。为了在按钮 4 和 5 之间留出空间,我们使用了嵌入在按钮 5 上方添加至少 10 个像素,然后使按钮 5 紧贴其单元格的底部边缘。

鉴于它们所占据的单元格,pane容器中的所有组件都尽可能宽。程序通过将GridBagConstraints fill实例变量设置为GridBagConstraints.HORIZONTAL来实现此 Object,对于所有组件,将其保留为该设置。如果程序未指定填充,则按钮将处于其自然宽度,如下所示:

具有默认填充值的 GridBagLayoutDemo。

放大 GridBagLayoutDemo 的窗口时,列将按比例增 Long。这是因为第一行中的每个组件为一列宽的每个组件都具有weightx = 0.5。这些组件的weightx的实际值并不重要。重要的是所有组件以及所有列的权重均大于 0.如果GridBagLayout管理 的组件均未设置weightx,则当组件的容器变宽时,组件将保留聚集成容器的中央,如下所示:

具有默认 weightx 值并由用户放大的 GridBagLayoutDemo。

如果为容器指定的大小小于或大于首选大小,则将根据GridBagContainer的重量分配任何空间。

请注意,如果放大窗口,则最后一行是唯一变高的行。这是因为只有按钮 5 的weighty大于零。

GridBagLayout API

GridBagLayoutGridBagConstraints类每个只有一个构造函数,没有参数。如Specifying Constraints所述,您无需操纵GridBagConstraints对象上的方法,而可以操纵其实例变量。通常,在GridBagLayout对象上调用的唯一方法是setConstraints,如范例说明所示。

使用 GridBagLayout 的示例

在本教程中,您可以找到使用GridBagLayout的示例。下表列出了一些。

ExampleWhere DescribedNotes
GridBagLayoutDemoThis section使用许多功能-权重,插图,内部填充,水平填充,精确的单元格位置,多列单元格和锚定(单元格内的组件定位)。
TextSamplerDemo使用 Literals 组件对齐两对标签和文本字段,并在容器的整个宽度上添加标签。
ContainerEventDemo如何编写容器侦听器使用重量,填充和相对位置在容器内放置五个组件。