文档

Java™ 教程
隐藏目录
Group布局示例
教程: 使用Swing创建GUI界面
课程: 在容器中布局组件
章节: 如何使用GroupLayout

GroupLayout示例


注意: 本课程涵盖了手写布局代码,这可能会有一定难度。如果您对布局管理的所有细节不感兴趣,您可能更喜欢使用GroupLayout布局管理器结合构建工具来布局您的GUI。一个这样的构建工具是NetBeans IDE。否则,如果您想手动编码并且不想使用GroupLayout,那么GridBagLayout是推荐的下一个最灵活和强大的布局管理器。

如果您有兴趣使用JavaFX创建GUI,请参阅JavaFX中的布局

作为使用GroupLayout创建GUI的示例,让我们为这个“查找”对话框创建一个布局:

Find.

水平布局

从左到右检查水平维度,我们可以看到有3个顺序的组。第一个实际上不是一个组,只是一个组件 - 标签。第二个是一个包含文本字段和复选框的组(我们稍后会拆分它)。第三个是两个按钮的组。如下所示:

Find.

让我们用代码勾勒出顺序组。请注意,GroupLayout.Alignment.LEADING对应水平维度中的左对齐。还请注意,我们没有指定间隙,假设启用了自动插入间隙功能。

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

现在让我们拆分中间的组。这是最难的一部分。有一个文本字段与两个复选框的序列并行。请参见以下插图:

Find_a2.

让我们添加相应的代码:

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
         .addComponent(textField)
         .addGroup(layout.createSequentialGroup()
              .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                  .addComponent(caseCheckBox)
                  .addComponent(wholeCheckBox))
              .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                  .addComponent(wrapCheckBox)
                  .addComponent(backCheckBox))))
     .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

我们希望文本字段能够调整大小,但这是自动发生的,因为JTextField默认返回正确的最大大小。

右侧的剩余组很简单:它只包含两个按钮。以下是代码:

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(textField)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(caseCheckBox)
                .addComponent(wholeCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(wrapCheckBox)
                .addComponent(backCheckBox))))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(findButton)
        .addComponent(cancelButton))
);

最后,我们希望按钮始终具有相同的大小,所以让我们将它们链接在一起:

layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

现在我们已经完成了水平维度。让我们切换到垂直维度。从现在开始,我们只需要考虑y轴。

垂直布局

在垂直维度上,我们从上到下检查布局。我们肯定希望第一行上的所有组件在基线上对齐。因此,沿着垂直轴有一个基线组的序列,后面是剩余组件的一个组。请参见以下图片。

Find_a3.

让我们先概述一下代码。首先,我们需要定义两个平行组。请注意,GroupLayout.Alignment.LEADING对应于垂直维度的顶部对齐。

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

我们可以立即填充基线组:

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

现在让我们来看看底部组。请注意,取消按钮与复选框不共享基线;它与顶部对齐。因此,第二个平行组包括按钮和两个基线组的序列组:

Find_a4.

对应的代码如下:

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(caseCheckBox)
                .addComponent(wrapCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(wholeCheckBox)
                .addComponent(backCheckBox)))
        .addComponent(cancelButton))
);

所以,我们已经创建了一个完整的布局,包括调整大小的行为,而不需要指定像素单位的具体数字 - 这是一个真正的跨平台布局。请注意,我们不需要指定组件之间的间距,自动获得正确的间距,以符合外观和感觉的指南。这是查找对话框布局的完整代码:

GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(textField)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(caseCheckBox)
                .addComponent(wholeCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(wrapCheckBox)
                .addComponent(backCheckBox))))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(findButton)
        .addComponent(cancelButton))
);
layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(caseCheckBox)
                .addComponent(wrapCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(wholeCheckBox)
                .addComponent(backCheckBox)))
        .addComponent(cancelButton))
);

这是完整的 Find.java 文件。您可以编译并运行它。尝试水平调整对话框的大小,看看布局如何自动调整到新的大小。


上一页:如何使用GroupLayout
下一页:如何使用SpringLayout