# 使用布局管理器

> 原文： [https://docs.oracle.com/javase/tutorial/uiswing/layout/using.html](https://docs.oracle.com/javase/tutorial/uiswing/layout/using.html)

布局管理器是实现`LayoutManager`接口 [*](#footnote) 并确定容器内组件的大小和位置的对象。虽然组件可以提供大小和对齐提示，但容器的布局管理器对容器内组件的大小和位置有最终决定权。

* * *

**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](../learn/index.html). 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](https://docs.oracle.com/javase/8/javafx/layout-tutorial/index.html) 中使用布局。

本节讨论与使用布局管理器相关的一些常见任务：

*   [设置布局管理器](#set)
*   [向容器添加组件](#add)
*   [提供尺寸和对齐提示](#sizealignment)
*   [在组件之间留出空间](#space)
*   [设置容器的方向](#orientation)
*   [选择布局管理器的提示](#choosing)
*   [第三方布局管理员](#thirdparty)

通常，您需要担心的布局管理器的唯一容器是 [`JPanel` s](../components/panel.html) 和[内容窗格](../components/toplevel.html#contentpane)。除非在创建`JPanel`时指定不同，否则每个`JPanel`对象都会初始化为使用`FlowLayout`。内容窗格默认使用`BorderLayout`。如果您不喜欢面板或内容窗格使用的默认布局管理器，则可以将其更改为其他布局管理器。但是，除非您使用`JToolBar`，否则`FlowLayout`和`BorderLayout`管理器仅适用于原型设计。任何真正的应用程序都需要重置布局管理器。同样，您应该使用适当的工具来执行此操作，而不是手动编写管理器。

您可以使用`JPanel`构造函数设置面板的布局管理器。例如：

```
JPanel panel = new JPanel(new BorderLayout());

```

创建容器后，可以使用`setLayout`方法设置其布局管理器。例如：

```
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());

```

虽然我们 _ 强烈建议您使用布局管理器 _，但您可以在没有它们的情况下执行布局。通过将容器的布局属性设置为 null，可以使容器不使用布局管理器。使用这种称为 _ 绝对定位 _ 的策略，您必须指定该容器中每个组件的大小和位置。绝对定位的一个缺点是，当调整顶层容器的大小时，它不能很好地调整。它也不能很好地适应用户和系统之间的差异，例如不同的字体大小和[语言环境](../../i18n/locale/index.html)。

将组件添加到面板或内容窗格时，为`add`方法指定的参数取决于面板或内容窗格正在使用的布局管理器。事实上，一些布局管理器甚至不要求您明确添加组件;例如，`GroupLayout`。例如，`BorderLayout`要求您使用以下代码指定应添加组件的区域（使用`BorderLayout`中定义的常量之一）：

```
pane.add(aComponent, BorderLayout.PAGE_START);

```

每个布局管理器的操作方法部分都详细说明了您需要为`add`方法指定的参数（如果有）。某些布局管理器（例如`GridBagLayout`和`SpringLayout`）需要精心设置的程序。但是，许多布局管理器只是根据组件添加到容器中的顺序放置组件。

除`JPanel`和内容窗格之外的 Swing 容器通常提供您应该使用的 API 而不是`add`方法。例如，不是直接将组件添加到[滚动窗格](../components/scrollpane.html)（或实际上，添加到其视口），而是在`JScrollPane`构造函数中指定组件或使用`setViewportView`。由于像这样的专用 API，您不需要知道许多 Swing 容器使用哪个布局管理器（如果有的话）。 （对于好奇：滚动窗格碰巧使用名为`ScrollPaneLayout`的布局管理器。）

有关如何将组件添加到特定容器的信息，请参阅容器的操作方法页面。您可以使用[如何使用各种组件](../components/componentlist.html)找到组件操作页面。

有时您需要自定义组件为其容器的布局管理器提供的大小提示，以便组件布局良好。您可以通过指定组件的一个或多个最小，首选和最大大小来执行此操作。您可以调用组件的方法来设置大小提示 - `setMinimumSize`，`setPreferredSize`和`setMaximumSize`。或者，您可以创建覆盖适当的 getter 方法的组件的子类 - `getMinimumSize`，`getPreferredSize`和`getMaximumSize`。以下是使组件的最大大小无限制的示例：

```
component.setMaximumSize(new Dimension(Integer.MAX_VALUE,
                                       Integer.MAX_VALUE));

```

许多布局管理器不关注组件所请求的最大大小。但是，`BoxLayout`和`SpringLayout`可以。此外，`GroupLayout`提供了明确设置最小，首选或最大尺寸的功能，而无需触摸组件。

除了提供大小提示外，您还可以提供对齐提示。例如，您可以指定两个组件的上边缘应对齐。您可以通过调用组件的`setAlignmentX`和`setAlignmentY`方法，或通过覆盖组件的`getAlignmentX`和`getAlignmentY`方法来设置对齐提示。尽管大多数布局管理器都忽略了对齐提示，但`BoxLayout`对它们表示尊重。您可以在[如何使用 BoxLayout](box.html) 中找到设置对齐的示例。

有三个因素影响容器中可见组件之间的空间量：

The layout manager

Some layout managers automatically put space between components; others do not. Some let you specify the amount of space between components. See the how-to page for each layout manager for information about spacing support.

Invisible components

You can create lightweight components that perform no painting, but that can take up space in the GUI. Often, you use invisible components in containers controlled by `BoxLayout`. See [How to Use BoxLayout](box.html) for examples of using invisible components.

Empty borders

No matter what the layout manager, you can affect the apparent amount of space between components by adding empty borders to components. The best candidates for empty borders are components that typically have no default border, such as panels and labels. Some other components might not work well with borders in some look-and-feel implementations, because of the way their painting code is implemented. For information about borders, see [How to Use Borders](../components/border.html).

本网站以英文撰写，文字从左到右，然后从上到下。但是，许多其他语言有不同的方向。 `componentOrientation`属性提供了一种指示特定组件应使用与默认从左到右，从上到下方向不同的方法的方法。在诸如单选按钮之类的组件中，方向可以用作外观应该切换按钮中图标和文本的位置的提示。在容器中，方向用作布局管理器的提示。

要设置容器的方向，可以使用`Component`定义的方法 [`setComponentOrientation`](https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html#setComponentOrientation-java.awt.ComponentOrientation-) ，或者也可以设置容器子项的方向， [`applyComponentOrientation`](https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html#applyComponentOrientation-java.awt.ComponentOrientation-) 。任一方法的参数可以是常数，例如`ComponentOrientation.RIGHT_TO_LEFT`，或者它可以是对`ComponentOrientation`方法 [`getOrientation(Locale)`](https://docs.oracle.com/javase/8/docs/api/java/awt/ComponentOrientation.html#getOrientation-java.util.Locale-) 的调用。例如，以下代码使所有`JComponent`都使用阿拉伯语语言环境进行初始化，然后相应地设置内容窗格及其中所有组件的方向：

```
JComponent.setDefaultLocale(new Locale("ar"));
JFrame frame = new JFrame();
...
Container contentPane = frame.getContentPane();
contentPane.applyComponentOrientation(
    ComponentOrientation.getOrientation(
        contentPane.getLocale()));

```

这里有两张图片显示`FlowLayout`如何在容器中放置完全相同的组件，除了它们的方向。

![FlowLayoutDemo with default, left-to-right orientation](img/acf1d6cee94083b9de2ccbb3be6c197a.jpg)
默认方向（从左到右）

![FlowLayoutDemo with right-to-left orientation](img/7ff31da7282201d9d5874c78e2dc38c4.jpg)
从右到左的方向

支持组件方向的标准布局管理器是`FlowLayout`，`BorderLayout`，`BoxLayout`，`GridBagLayout`和`GridLayout`。

* * *

**Note:** Care must be taken that the component orientation is applied to renderers, editors and any other components unreachable through normal traversal of the containment hierarchy.

* * *

布局管理者有不同的优点和缺点。本节讨论一些常见的布局方案，以及哪些布局管理器可能适用于每个方案。但是，强烈建议您使用构建器工具来创建布局管理器，例如 [NetBeans IDE Matisse GUI 构建器](http://netbeans.org/kb/trails/matisse.html)，而不是手动编写管理器。下面列出的方案仅供参考，以便您对在不同情况下使用哪种类型的经理感到好奇，或者您绝对必须手动为经理编码。

如果我们讨论的布局管理器都不适合您的情况并且您无法使用构建器工具，请随意使用您可能编写或查找的其他布局管理器。另外请记住，`GridBagLayout`和`SpringLayout`等灵活的布局管理器可以满足许多布局需求。

**Scenario:** You need to display a component in as much space as it can get.

If it is the only component in its container, use [`GridLayout`](grid.html) or [`BorderLayout`](border.html). Otherwise, `BorderLayout` or [`GridBagLayout`](gridbag.html) might be a good match.

如果使用`BorderLayout`，则需要将占用空间的组件放在中间位置。使用`GridBagLayout`，您需要设置组件的约束以便`fill=GridBagConstraints.BOTH`。另一种可能性是使用 [`BoxLayout`](box.html) ，使得占用空间的组件指定非常大的首选和最大尺寸。

**Scenario:** You need to display a few components in a compact row at their natural size.

Consider using a `JPanel` to group the components and using either the `JPanel`'s default [`FlowLayout`](flow.html) manager or the [`BoxLayout`](box.html) manager. [`SpringLayout`](spring.html) is also good for this.

**Scenario:** You need to display a few components of the same size in rows and columns.

[`GridLayout`](grid.html) is perfect for this.

**Scenario:** You need to display a few components in a row or column, possibly with varying amounts of space between them, custom alignment, or custom component sizes.

[`BoxLayout`](box.html) is perfect for this.

**Scenario:** You need to display aligned columns, as in a form-like interface where a column of labels is used to describe text fields in an adjacent column.

[`SpringLayout`](spring.html) is a natural choice for this. The `SpringUtilities` class used by several Tutorial examples defines a `makeCompactGrid` method that lets you easily align multiple rows and columns of components.

**Scenario:** You have a complex layout with many components.

Consider either using a very flexible layout manager such as [`GridBagLayout`](gridbag.html) or [`SpringLayout`](spring.html), or grouping the components into one or more `JPanel`s to simplify layout. If you take the latter approach, each `JPanel` might use a different layout manager.

其他第三方布局管理器由 Swing 社区创建，以补充 Java 平台提供的那些。以下列表绝不是明确的，但下面列出的布局管理器是最受欢迎的：

*   [MiGLayout](http://www.miglayout.com/)
*   [Karsten Lentzsch 的 FormLayout](http://www.jgoodies.com/)

* * *

*  ，第二个接口`LayoutManager2`被引入。 `LayoutManager2`扩展了`LayoutManager`，为最大尺寸和对齐提供支持。 `LayoutManager2`还添加了`addLayoutComponent`，`Object`和`invalidateLayout`。布局管理器还需要`LayoutManager2`提供的通知，因此任何现代布局管理器都需要实现它。