Java教程是针对JDK 8编写的。本页面描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅Java语言更改,了解Java SE 9及其后续版本中更新的语言特性的概述。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息。
布局管理器是实现了LayoutManager
接口的对象,它确定容器内组件的大小和位置。虽然组件可以提供大小和对齐的提示,但容器的布局管理器决定组件在容器内的大小和位置。
GroupLayout
布局管理器结合构建工具来布局你的GUI。其中一个这样的构建工具是NetBeans IDE。否则,如果你想手动编码而且不想使用GroupLayout
,那么GridBagLayout
作为下一个最灵活和强大的布局管理器是推荐的。
如果你想使用JavaFX来创建GUI,请参阅JavaFX中的布局。
本节讨论了使用布局管理器相关的一些常见任务:
通常情况下,你只需要关注JPanel
和内容面板content panes
的布局管理器。每个JPanel
对象在创建时会初始化为使用FlowLayout
,除非在创建JPanel
时另有指定。内容面板默认使用BorderLayout
。如果你不喜欢面板或内容面板使用的默认布局管理器,你可以自由地将其更改为其他布局管理器。然而,除非你使用JToolBar
,否则FlowLayout
和BorderLayout
布局管理器只适用于原型设计。任何真实的应用程序都需要重新设置布局管理器。同样,你应该使用适当的工具来完成这项任务,而不是手动编写管理器。
你可以使用JPanel
构造函数设置面板的布局管理器。例如:
JPanel panel = new JPanel(new BorderLayout());
在创建容器后,你可以使用setLayout
方法设置其布局管理器。例如:
Container contentPane = frame.getContentPane(); contentPane.setLayout(new FlowLayout());
虽然我们强烈建议使用布局管理器,但您也可以在没有布局管理器的情况下进行布局。通过将容器的布局属性设置为null,可以使容器不使用布局管理器。使用这种称为绝对定位的策略,您必须指定容器内每个组件的大小和位置。绝对定位的一个缺点是它在调整顶层容器大小时不会很好地调整。它也无法很好地适应用户和系统之间的差异,例如不同的字体大小和语言环境。
当您将组件添加到面板或内容窗格时,您在add
方法中指定的参数取决于面板或内容窗格使用的布局管理器。实际上,有些布局管理器甚至不需要您显式地添加组件;例如GroupLayout
。例如,BorderLayout
要求您使用类似下面的代码指定组件应添加到的区域(使用BorderLayout
中定义的常量之一):
pane.add(aComponent, BorderLayout.PAGE_START);
每个布局管理器的“如何使用”部分都详细说明了您需要在add
方法中指定的参数。某些布局管理器(例如GridBagLayout
和SpringLayout
)需要复杂的设置过程。然而,许多布局管理器只是根据它们添加到容器的顺序来放置组件。
除了JPanel
和内容窗格之外,Swing容器通常提供应使用而不是add
方法的API。例如,您可以在直接添加到滚动窗格(或者实际上添加到其视口)而不是在JScrollPane
构造函数中指定组件,或者使用setViewportView
。由于有了这样的专用API,您不需要知道许多Swing容器使用的布局管理器(如果有的话)。 (对于好奇的人:滚动窗格恰好使用名为ScrollPaneLayout
的布局管理器。)
有关如何向特定容器添加组件的信息,请参阅容器的相关页面。您可以使用如何使用各种组件找到组件的相关页面。
有时,您需要自定义组件向其容器的布局管理器提供的大小提示,以便组件能够良好地布局。您可以通过指定组件的最小、首选和最大尺寸之一或多个来实现这一点。您可以调用组件的设置大小提示的方法 - 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中找到设置对齐的示例。
容器中可见组件之间的间距受到以下三个因素的影响:
BoxLayout
控制的容器中使用不可见组件。请参考如何使用BoxLayout,了解使用不可见组件的示例。
本网站使用英语编写,文本从左到右,然后从上到下。然而,许多其他语言具有不同的方向。 componentOrientation
属性提供了一种指示特定组件应使用与默认的从左到右、从上到下方向不同的方向的方式。在像单选按钮这样的组件中,方向可能被用作提示,表示外观应该在按钮中切换图标和文本的位置。在容器中,方向被用作布局管理器的提示。
要设置容器的方向,您可以使用Component
定义的setComponentOrientation
方法,或者为了设置容器的子组件的方向,可以使用applyComponentOrientation
方法。这两个方法的参数可以是常量,如ComponentOrientation.RIGHT_TO_LEFT
,也可以是调用ComponentOrientation
方法getOrientation(Locale)
的结果。例如,以下代码会使所有的JComponent
都使用阿拉伯语环境进行初始化,并相应地设置内容面板和其中的所有组件的方向:
JComponent.setDefaultLocale(new Locale("ar")); JFrame frame = new JFrame(); ... Container contentPane = frame.getContentPane(); contentPane.applyComponentOrientation( ComponentOrientation.getOrientation( contentPane.getLocale()));
下面的两张图片展示了FlowLayout
在方向完全相同但是容器不同的情况下如何布局组件。
默认方向(从左到右)
从右到左的方向
支持组件方向的标准布局管理器包括FlowLayout
、BorderLayout
、BoxLayout
、GridBagLayout
和GridLayout
。
布局管理器具有不同的优势和劣势。本节讨论了一些常见的布局场景以及每种布局管理器适用的场景。然而,再次强烈建议您使用构建工具来创建布局管理器,例如NetBeans IDE Matisse GUI builder,而不是手动编码管理器。下面列出的场景仅供参考,以了解在不同情况下使用哪种类型的管理器,或者如果您绝对必须手动编码管理器。
如果我们讨论的布局管理器都不适合您的情况,而且您不能使用构建工具,可以自由地使用您编写或找到的其他布局管理器。还要记住,像GridBagLayout
和SpringLayout
这样的灵活布局管理器可以满足许多布局需求。
GridLayout
或BorderLayout
。否则,BorderLayout
或GridBagLayout
可能是一个很好的选择。
如果使用BorderLayout
,您需要将占用空间较大的组件放在中心位置。如果使用GridBagLayout
,您需要为组件设置约束条件,使fill=GridBagConstraints.BOTH
。另一种可能性是使用BoxLayout
,使占用空间较大的组件指定非常大的首选大小和最大大小。
JPanel
来分组组件,并使用JPanel
的默认FlowLayout
管理器或BoxLayout
管理器。对于这种情况,SpringLayout
也很适合。
GridLayout
非常适合这种情况。
BoxLayout
非常适合这种情况。
SpringLayout
对此是一个很自然的选择。几个教程示例使用的SpringUtilities
类定义了一个makeCompactGrid
方法,可让您轻松地对齐多行多列的组件。
GridBagLayout
或SpringLayout
,或将组件分组到一个或多个JPanel
中以简化布局。如果采用后一种方法,每个JPanel
可能使用不同的布局管理器。
Java平台提供的布局管理器已经得到了Swing社区的补充,创建了其他第三方布局管理器。以下列表并非绝对,但下面列出的布局管理器是最受欢迎的:
*在JDK 1.1时代引入了第二个接口LayoutManager2
。 LayoutManager2
扩展了LayoutManager
,提供了最大尺寸和对齐的支持。 LayoutManager2
还添加了addLayoutComponent
方法,它接受一个Object
参数,并且有一个invalidateLayout
方法。布局管理器还需要LayoutManager2
提供的通知,因此任何现代布局管理器都需要实现它。