如何使用 BoxLayout

Note:

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

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

Swing 软件包包括一个名为BoxLayout的通用布局 管理 器。 BoxLayout既可以将其组件堆叠在一起,也可以将它们排成一行-您可以选择。您可能会认为它是FlowLayout的版本,但功能更强大。这是一个应用程序的图片,它演示了使用BoxLayout显示组件的居中列:

BoxLayoutDemo 的快照

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

您可以在BoxLayoutDemo.java中查看代码。

下图显示了使用BoxLayout的两个实例的 GUI。在 GUI 的顶部,从顶部到底部的框布局在滚动窗格上方放置了一个标签。在 GUI 的底部,从左到右的框布局将两个按钮彼此相邻放置。 BorderLayout组合了 GUI 的两个部分,并确保将多余的空间分配给滚动窗格。

同时使用从左到右和从上到下的框布局

您可以在“使用 Swing 组件”的example index中找到运行 ListDialog 及其源文件的链接。

以下代码取自ListDialog.java,布置了 GUI。此代码在对话框的构造函数中,该对话框以JDialog子类实现。粗体的代码行设置了框布局,并向其中添加了组件。

JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
listScroller.setAlignmentX(LEFT_ALIGNMENT);
...
//Lay out the label and scroll pane from top to bottom.
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
JLabel label = new JLabel(labelText);
...
listPane.add(label);
listPane.add(Box.createRigidArea(new Dimension(0,5)));
listPane.add(listScroller);
listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

//Lay out the buttons from left to right.
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(cancelButton);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(setButton);

//Put everything together, using the content pane's BorderLayout.
Container contentPane = getContentPane();
contentPane.add(listPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.PAGE_END);

第一行粗线创建了一个从上到下的框布局,并将其设置为listPane的布局 管理 器。 BoxLayout构造函数的两个参数是它 管理 的容器以及将沿其放置组件的轴。 PAGE_AXIS常量指定应按照目标容器的ComponentOrientation属性所确定的方向,在行跨页面的方向上排列组件。 LINE_AXIS常量指定应按目标容器的ComponentOrientation属性确定的文本行方向排列组件。这些常量允许国际化,方法是将组件以正确的从左到右,从右到左或从上到下的方向放置在其容器中。

接下来的三行粗线将标签和滚动窗格添加到容器中,并用一个“刚性区域”将它们分隔开-一个不可见的组件,用于在组件之间添加空间。在这种情况下,刚性区域没有宽度,并且在标签和滚动窗格之间恰好放置了 5 个像素。稍后在使用不可见的零部件作为填充物中讨论刚性区域。

下一个粗体代码块将创建一个从左到右的框布局,并将其设置为buttonPane容器。然后,代码将两个按钮添加到容器中,并使用一个刚性区域在按钮之间放置 10 个像素。要将按钮放在其容器的右侧,添加到容器的第一个组件是* glue *。这种胶水是一种不可见的成分,可以根据需要增 Long 以吸收其容器中的任何多余空间。胶水在使用不可见的零部件作为填充物中讨论。

作为使用不可见组件的替代方法,有时可以使用空白边框在组件(尤其是面板)周围创建空间。例如,前面的代码段使用空白边框在对话框的所有侧面与其内容之间以及内容的两个部分之间放置 10 个像素。边框完全独立于布局 管理 器。它们只是 Swing 组件绘制边缘的方式,并在组件内容和边缘之间提供填充。有关更多信息,请参见如何使用边框

以下各节将详细讨论BoxLayout

不要让BoxLayout讨论的 Long 度吓到您!您可能可以将BoxLayout与已经拥有的信息一起使用。如果您遇到麻烦或想利用BoxLayout的功能,请 continue 阅读。

框布局功能

如前所述,BoxLayout将组件彼此重叠或成行排列。在盒式布局安排零部件时,它会考虑零部件的对齐方式以及最小,首选和最大尺寸。在本节中,我们将讨论从上到下的布局。相同的概念适用于从左到右或从右到左的布局。您只需将 X 替换为 Y,将高度替换为宽度,依此类推。

Version note:

在 JDK 1.4 版之前,不存在用于以可本地化的方式指定框布局的轴的常量。而是在创建BoxLayout时指定了X_AXIS(从左到右)或Y_AXIS(从上到下)。我们的示例现在使用常量LINE_AXISPAGE_AXIS,它们是首选,因为它们使程序能够适应具有不同方向的语言。在默认的从左到右方向上,LINE_AXIS指定从左到右的布局,PAGE_AXIS指定从上到下的布局。

BoxLayout从顶部到底部对组件进行布局时,它会try按组件的首选高度调整每个组件的大小。如果布局的垂直空间与首选高度的总和不匹配,则BoxLayouttry调整组件的大小以填充该空间。组件会增加或缩小以填充空间,其中BoxLayout表示每个组件的最小和最大大小。容器底部会出现任何多余的空间。

对于顶部到底部的框布局,容器的首选宽度是子级的最大首选宽度。如果强制容器宽于此宽度,BoxLayout将try将每个组件的宽度调整为容器宽度的宽度(减去插图)。如果组件的最大尺寸小于容器的宽度,则 X 对齐起作用。

X 对齐方式不仅影响组件之间的相对位置,还影响组件(作为一个组)在其容器内的位置。下图说明了具有最大宽度限制的组件的对齐方式。

三个左对齐的组件

三个中心对齐的组件

三个右对齐的组件

在第一张图中,所有三个分量的 X 对齐方式均为 0.0(Component.LEFT_ALIGNMENT)。这意味着组件的左侧应对齐。此外,这意味着所有三个组件都尽可能地位于其容器的最左侧。

在第二张图中,所有三个分量的 X 对齐为 0.5(Component.CENTER_ALIGNMENT)。这意味着组件的中心应对齐,并且组件应位于其容器的水平中心。

在第三张图中,组件的 X 对齐为 1.0(Component.RIGHT_ALIGNMENT)。您可以猜测这对于组件相对于其容器的对齐和位置意味着什么。

您可能想知道当零部件的最大尺寸受到限制并且 X 对齐方式不同时会发生什么。下图显示了一个示例:

具有混合 X 对齐的三个分量

如您所见,X 对齐为 0.0(Component.LEFT_ALIGNMENT)的组件的左侧与 0.5 X 对齐(Component.CENTER_ALIGNMENT)的组件的中心对齐,而 X 对齐的组件的右侧与具有 X 对齐的组件的中心对齐。 X 对齐 1.0(Component.RIGHT_ALIGNMENT)。 解决对齐问题中将进一步讨论这种混合对齐方式。

如果所有组件都没有最大宽度怎么办?在这种情况下,如果所有组件都具有相同的 X 对齐,则将所有组件制作得与其容器一样宽。如果 X 对齐方式不同,则 X 对齐方式为 0.0(左)或 1.0(右)的任何分量都将较小。具有中间 X 对齐(例如中心)的所有组件都将与其容器一样宽。这是两个示例:

具有混合 X 对齐且没有最大尺寸的三个组件

具有混合 X 对齐且没有最大尺寸的三个组件

为了更好地了解BoxLayout,您可以使用 BoxLayoutDemo2 运行自己的实验。

Try this:

您可以在BoxLayoutDemo2.java中查看代码。
您将看到一个类似于上面的窗口,其中包含三个矩形。每个矩形都是BLDComponent的实例,而BLDComponentJComponent的子类。

  • 在一个矩形内单击。
    这就是更改矩形的 X 对齐方式的方式。

  • 单击窗口底部的复选框。
    这将关闭所有矩形的受限大小。

  • 使窗户更高。
    这使矩形的容器大于矩形的首选大小的总和。容器是带有红色轮廓的JPanel,因此您可以知道容器的边缘在哪里。

使用不可见的零部件作为填充物

由盒子布局控制的每个组件都紧靠其相邻组件。如果要在组件之间留出空间,则可以为一个或两个组件添加空的border,或插入不可见的组件以提供空间。您可以在Box类的帮助下创建不可见的组件。

Box类定义了一个嵌套类Box.Filler,该类是一个透明组件,不绘制任何内容,并用于在其他组件之间提供空间。但是,Filler实际上不是不可见的,因为未调用setVisible(false)Box类提供了方便的方法来帮助您创建常见的填充物。下表提供了有关使用BoxBox.Filler创建不可见组件的详细信息。

TypeSize Constraints如何构建
rigid area具有混合 X 对齐且没有最大尺寸的三个组件Box.createRigidArea(size)
glue, horizontal具有混合 X 对齐且没有最大尺寸的三个组件Box.createHorizontalGlue()
glue, vertical具有混合 X 对齐且没有最大尺寸的三个组件Box.createVerticalGlue()
custom Box.Filler(as specified)new Box.Filler(minSize, prefSize, maxSize)

以下是您通常使用每种填充物的方式:

  • Rigid area

    • 当您希望两个组件之间有固定大小的空间时,请使用此选项。例如,要在从左到右的两个组件之间放置 5 个像素,可以使用以下代码:
container.add(firstComponent);
container.add(Box.createRigidArea(new Dimension(5,0)));
container.add(secondComponent);

没有刚性区域

刚性区域


注意: Box类提供了另一种填充物,用于在组件之间放置固定空间:垂直或水平支柱。不幸的是,支杆具有无限的最大高度或宽度(分别用于水平和垂直支杆)。这意味着,例如,如果在垂直框中使用水平框,则水平框有时可能会变得过高。因此,我们建议您使用刚性区域而不是支柱。


  • Glue

    • 使用此选项可以指定布局中多余的空间。可以将它视为一种弹性胶水-可拉伸且可扩展,但除非将其所粘附的组件拆开,否则不会占用空间。例如,通过在左右框中的两个组件之间放置水平胶水,可以在这些组件之间留出多余的空间,而不是在所有组件的右边。这是一个使左右框中的空间位于两个组件之间而不是组件右侧的示例:
container.add(firstComponent);
container.add(Box.createHorizontalGlue());
container.add(secondComponent);

无水平胶

With glue

  • Custom Box.Filler

    • 使用此选项可以指定具有所需最小,首选和最大尺寸的组件。例如,要以从左到右的布局创建一些填充物,以在两个组件之间放置至少 5 个像素,并确保容器的最小高度为 100 像素,则可以使用以下代码:
container.add(firstComponent);
Dimension minSize = new Dimension(5, 100);
Dimension prefSize = new Dimension(5, 100);
Dimension maxSize = new Dimension(Short.MAX_VALUE, 100);
container.add(new Box.Filler(minSize, prefSize, maxSize));
container.add(secondComponent);

无定制填料

带定制填充物

解决对齐问题

BoxLayout有时会出现两种对齐问题:

  • 一组组件都具有相同的对齐方式,但是您想更改它们的对齐方式以使它们看起来更好。例如,您可能希望按钮的底部对齐,而不是将一组左右按钮的中心全部排成一行。这是一个例子:

Customizing alignment

  • BoxLayout控制的两个或多个组件具有不同的默认对齐方式,这导致它们未对齐。例如,如下所示,如果标签和面板处于自上而下的盒子布局中,则默认情况下,标签的左边缘与面板的中心对齐。

X 对齐不匹配

通常,由上至下的BoxLayout对象控制的所有组件都应具有相同的 X 对齐方式。同样,从左到右Boxlayout控制的所有组件通常应具有相同的 Y 对齐。您可以通过调用setAlignmentX方法来设置JComponent的 X 对齐方式。所有组件可用的替代方法是重写组件类的自定义子类中的getAlignmentX方法。同样,可以通过调用setAlignmentY方法或覆盖getAlignmentY来设置组件的 Y 对齐方式。

这是一个示例,取自名为BoxAlignmentDemo的应用程序,该示例更改两个按钮的 Y 对齐方式,以使按钮的底部对齐:

button1.setAlignmentY(Component.BOTTOM_ALIGNMENT);
button2.setAlignmentY(Component.BOTTOM_ALIGNMENT);

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

默认情况下,大多数组件的中心 X 和 Y 对齐。但是,按钮,组合框,标签和菜单项具有不同的默认 X 对齐值:LEFT_ALIGNMENT。上一张图片显示了将左对齐的组件(例如标签)和居中对齐的组件放在由顶部到底部BoxLayout控制的容器中会发生什么情况。

BoxAlignmentDemo程序提供了解决不匹配对齐问题的示例。通常,这就像将有问题的按钮或标签居中对齐一样简单。例如:

label.setAlignmentX(Component.CENTER_ALIGNMENT);

指定组件尺寸

如前所述,BoxLayout注意组件所要求的最小,首选和最大尺寸。在微调布局时,可能需要调整这些大小。

有时显然需要调整大小。例如,按钮的最大大小通常与其首选大小相同。如果希望在有更多空间可用时将按钮绘制得更宽,则需要更改其最大大小。

但是,有时调整大小的需求不是很明显。使用盒子布局可能会得到意想不到的结果,并且您可能不知道为什么。在这种情况下,通常最好首先将问题视为alignment problem。如果调整 Route 没有帮助,则可能是尺寸问题。我们将在稍后进一步讨论。

Note:

尽管BoxLayout注意组件的最大大小,但许多布局 管理 器却没有。例如,如果将按钮放在BorderLayout的底部,则无论按钮的最大大小是多少,该按钮都可能比其首选宽度更宽。 BoxLayout另一方面,按钮的宽度绝不能超过其最大尺寸。

您可以通过两种方式更改最小,首选和最大大小:

  • 通过调用适当的setXxxSize方法(由JComponent类定义)。例如:
comp.setMinimumSize(new Dimension(50, 25));
comp.setPreferredSize(new Dimension(50, 25));
comp.setMaximumSize(new Dimension(Short.MAX_VALUE,
                                  Short.MAX_VALUE));
  • 通过覆盖适当的getXxxSize方法。例如:
...//in a subclass of a component class:
public Dimension getMaximumSize() {
    size = getPreferredSize();
    size.width = Short.MAX_VALUE;
    return size;
}

如果您在使用盒式布局时遇到麻烦,并且已经排除了对齐问题,那么问题很可能与尺寸有关。例如,如果由盒子布局控制的容器占用了太多空间,则容器中的一个或多个组件可能需要限制其最大大小。

您可以使用两种技术来跟踪盒式布局中的尺寸问题:

  • 在有关的 Swing 组件的外部添加一条粗线border。这使您可以看到它们的实际大小。例如:
comp.setBorder(BorderFactory.createCompoundBorder(
                   BorderFactory.createLineBorder(Color.red),
                   comp.getBorder()));
  • 使用System.out.println打印组件的最小,首选和最大大小,以及它们的边界。

Box 布局 API

下表列出了常用的BoxLayoutBox构造函数和方法。使用框式布局的 API 分为以下几类:

创建 BoxLayout 对象

构造函数或方法Purpose
BoxLayout(Container, int)创建一个BoxLayout实例,该实例控制指定的Container。整数参数指定容器组件的布置方向。当容器具有默认的组件方向时,BoxLayout.LINE_AXIS指定将组件从左到右进行布局,BoxLayout.PAGE_AXIS指定将组件从上到下进行布局。
Box(int)创建一个Box-一个使用带有指定轴的BoxLayout的容器。
static Box createHorizontalBox()

(在Box中)
创建一个Box,从左到右布置其组件。
static Box createVerticalBox()
(在Box中)
创建一个Box,从上到下布置其组件。

创建空间填充物
这些方法在Box类中定义.

构造函数或方法Purpose
Component createRigidArea(Dimension)创建一个rigid组件。
Component createHorizontalGlue() Component createVerticalGlue() Component createGlue()创建一个glue组件。水平胶和垂直胶可能非常有用。
Component createHorizontalStrut() Component createVerticalStrut()创建一个“ strut”组件。我们建议使用刚性区域而不是支柱。
Box.Filler(Dimension, Dimension, Dimension)创建具有指定的最小,首选和最大大小的组件(使用该 Sequences 指定的参数)。有关详细信息,请参见本节前面的custom Box.Filler讨论。

其他有用的方法

MethodPurpose
void changeShape(Dimension, Dimension, Dimension) (在Box.Filler中)更改收件人Box.Filler对象的最小,首选和最大大小。布局会相应更改。

使用框式布局的示例

下表列出了许多使用框式布局的示例。

ExampleWhere DescribedNotes
BoxLayoutDemo2This page使用盒式布局创建组件的居中列。
BoxAlignmentDemoThis page演示如何解决常见的对齐问题。
BoxLayoutDemoThis page使您可以使用对齐方式和最大尺寸播放。
ListDialogThis page一个简单但实际的示例,它同时使用了从上到下的框布局和从左到右的布局。使用水平胶水,刚性区域和空边框。还设置零部件的 X 对齐方式。
InternalFrameEventDemo如何编写内部框架侦听器使用从上到下的布局将按钮和内部窗格中的滚动窗格居中。
MenuGlueDemo自定义菜单布局显示如何使用胶水组件在菜单栏中右对齐菜单。
MenuLayoutDemo自定义菜单布局显示如何通过更改菜单栏以使用从上到下的框布局,以及更改弹出菜单以使用从左到右的框布局来自定义菜单布局。
Converter演示中的ConversionPanel.java如何使用面板通过将组件的宽度设置为相同,并将它们的容器的宽度设置为相同,在不同的盒式布局控制的容器中对齐两个组件。