GroupLayout 示例

原文: https://docs.oracle.com/javase/tutorial/uiswing/layout/groupExample.html


Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.


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

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

Find.

水平布局

从左到右检查水平尺寸*,我们可以看到序列中有 3 组。第一个实际上不是一个组,只是一个组件 - 标签。第二个是包含文本字段和复选框的组(稍后我们将对其进行分解)。第三个是两个按钮组。如下图所示:_

Find.

让我们在代码中勾画出顺序组。请注意,GroupLayout.Alignment.LEADING对应于水平维度中的左对齐。另请注意,假设间隙自动插入功能已打开,我们不会指定间隙。

  1. layout.setHorizontalGroup(layout.createSequentialGroup()
  2. .addComponent(label)
  3. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
  4. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
  5. );

现在让我们在中间分解这个群体。这是最难的一个。有一个文本字段与两个并行组的序列并行,每个组包含两个复选框。请参见下图:

Find_a2.

让我们添加相应的代码:

  1. layout.setHorizontalGroup(layout.createSequentialGroup()
  2. .addComponent(label)
  3. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  4. .addComponent(textField)
  5. .addGroup(layout.createSequentialGroup()
  6. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  7. .addComponent(caseCheckBox)
  8. .addComponent(wholeCheckBox))
  9. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  10. .addComponent(wrapCheckBox)
  11. .addComponent(backCheckBox))))
  12. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
  13. );

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

右边的剩余组是微不足道的:它只包含两个按钮。这是代码:

  1. layout.setHorizontalGroup(layout.createSequentialGroup()
  2. .addComponent(label)
  3. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  4. .addComponent(textField)
  5. .addGroup(layout.createSequentialGroup()
  6. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  7. .addComponent(caseCheckBox)
  8. .addComponent(wholeCheckBox))
  9. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  10. .addComponent(wrapCheckBox)
  11. .addComponent(backCheckBox))))
  12. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  13. .addComponent(findButton)
  14. .addComponent(cancelButton))
  15. );

最后,我们希望按钮的大小始终相同,所以让我们链接它们:

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

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

垂直布局

在垂直维度中,我们检查从顶部到底部的布局。我们绝对希望第一行的所有组件在基线上对齐。因此,沿着垂直轴,存在基线组的序列,接着是一组剩余的组件。见下图。

Find_a3.

让我们勾勒出代码。首先,我们需要定义两个并行组。请注意,GroupLayout.Alignment.LEADING对应于垂直维度中的顶部对齐。

  1. layout.setVerticalGroup(layout.createSequentialGroup()
  2. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE))
  3. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
  4. );

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

  1. layout.setVerticalGroup(layout.createSequentialGroup()
  2. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  3. .addComponent(label)
  4. .addComponent(textField)
  5. .addComponent(findButton))
  6. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
  7. );

现在让我们看一下底层组。请注意,取消按钮不在复选框的共享基线上;它在顶部对齐。因此,第二个并行组包含按钮和两个基线组的连续组,其中包含复选框:

Find_a4.

相应的代码如下:

  1. layout.setVerticalGroup(layout.createSequentialGroup()
  2. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  3. .addComponent(label)
  4. .addComponent(textField)
  5. .addComponent(findButton))
  6. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  7. .addGroup(layout.createSequentialGroup()
  8. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  9. .addComponent(caseCheckBox)
  10. .addComponent(wrapCheckBox))
  11. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  12. .addComponent(wholeCheckBox)
  13. .addComponent(backCheckBox)))
  14. .addComponent(cancelButton))
  15. );

因此,我们创建了一个完整的布局,包括调整大小行为,而不指定像素中的单个数字 - 真正的跨平台布局。请注意,我们不需要指定组件之间的间隙,我们会根据外观指导自动获得正确的间距。以下是“查找”对话框布局的完整代码:

  1. GroupLayout layout = new GroupLayout(getContentPane());
  2. getContentPane().setLayout(layout);
  3. layout.setAutoCreateGaps(true);
  4. layout.setAutoCreateContainerGaps(true);
  5. layout.setHorizontalGroup(layout.createSequentialGroup()
  6. .addComponent(label)
  7. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  8. .addComponent(textField)
  9. .addGroup(layout.createSequentialGroup()
  10. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  11. .addComponent(caseCheckBox)
  12. .addComponent(wholeCheckBox))
  13. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  14. .addComponent(wrapCheckBox)
  15. .addComponent(backCheckBox))))
  16. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  17. .addComponent(findButton)
  18. .addComponent(cancelButton))
  19. );
  20. layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);
  21. layout.setVerticalGroup(layout.createSequentialGroup()
  22. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  23. .addComponent(label)
  24. .addComponent(textField)
  25. .addComponent(findButton))
  26. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
  27. .addGroup(layout.createSequentialGroup()
  28. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  29. .addComponent(caseCheckBox)
  30. .addComponent(wrapCheckBox))
  31. .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
  32. .addComponent(wholeCheckBox)
  33. .addComponent(backCheckBox)))
  34. .addComponent(cancelButton))
  35. );

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