// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= 使用 GridBag 定制器设计高级 Java 窗体
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: 使用 GridBag 定制器设计高级 Java 窗体 - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, 使用 GridBag 定制器设计高级 Java 窗体

作者：Jan Stola、Tomas Pavek 和 Alyona Stashkova

本教程是一个系列教程的第二部分（共两个部分），介绍了如何使用 NetBeans IDE GridBag 定制器的高级功能设计高级 Java 窗体。
该系列教程可作为一个指南，介绍了如何设置 GUI 组件布局而无需手动编写布局代码，然后在现有窗体中进行其他更改，以实现项目所需的特定目标布局。

该系列教程中的每个文档都介绍了一组特定的功能。

* 第 1 部分：link:../java/gbcustomizer-basic.html[+使用 GridBag 定制器设计基本 Java 窗体+]
* 第 2 部分：使用 GridBag 定制器设计高级 Java 窗体

link:../java/gbcustomizer-basic.html[+该系列中的第一个教程+]介绍了如何使用 NetBeans IDE GridBag 定制器的基本功能修改简单的 Java 窗体。在本教程中，将了解如何使用 GridBag 定制器的高级功能更改现有的窗体布局。


image::images/netbeans-stamp-80-74.png[title="此页上的内容适用于 NetBeans IDE 7.1 和更高版本"]


*要学习本教程，您需要具备以下软件和资源。*

|===
|软件或资源 |要求的版本 

|link:http://netbeans.org/downloads/index.html[+NetBeans IDE+] |7.1 或更高版本 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java 开发工具包 (JDK)+] |版本 6、7 或 8 

|link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJava%252Fgbcustomizer-advanced-tutorial.zip[+gbcustomizer-advanced-tutorial.zip+] |一个具有演示项目的档案文件，其中包含初始和目标教程布局。 
|===

*注：*

* 您可以将用作该系列教程起点的项目作为  ``.zip``  档案文件进行下载。
* 本教程仅重点介绍如何设计容器的布局。在 GUI 中添加功能超出了本教程的范围。


== 打开示例项目

在开始借助 GridBag 定制器设置组件布局之前，请下载 link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJava%252Fgbcustomizer-advanced-tutorial.zip[+gbcustomizer-advanced-tutorial.zip+]，将  ``GridBagCustomizerAdvancedTutorial``  项目解压缩到您的硬盘驱动器上，然后在 NetBeans IDE 中打开该项目。

1. 下载 link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJava%252Fgbcustomizer-advanced-tutorial.zip[+gbcustomizer-advanced-tutorial.zip+] 项目，并将其解压缩到您计算机上的任何位置。
2. 在 NetBeans IDE 的 "Projects"（项目）标签中，单击 "File"（文件）菜单上的 "Open Project"（打开项目），导航至在上一步中解压缩的  ``GridBagCustomizerAdvancedTutorial``  项目，然后单击 "Open Project"（打开项目）。项目文件夹可能包含在也称为  ``GridBagCustomizerAdvancedTutorial``  的文件夹中。

*注：* ``GridBagCustomizerAdvancedTutorial``  项目使用  ``JUnit``  和  ``JUnit 4``  类库，这些库位于更新中心内。需要在 "Open project"（打开项目）对话框中单击 "Resolve Problems"（解决问题），然后在 "Resolve Reference Problems"（解决引用问题）对话框中单击 "Resolve"（解决），并按照 NetBeans IDE 安装程序中的说明安装 JUnit 插件。安装完成后，单击 "Finish"（完成）以关闭 "NetBeans IDE Installer"（NetBeans IDE 安装程序）对话框，然后单击 "Close"（关闭）以关闭 "Resolve Reference Problems"（解决引用问题）对话框。



. 展开 ``源包 > tutorial`` ，然后双击  ``ContactsAdvancedInitial.java`` 。
此时将在 GUI 构建器的 "Design"（设计）视图中打开样例窗体。

[.feature]
--
image::images/sampleform-small.png[role="left", link="images/sampleform.png"]
--


== 调用 GridBag 定制器

要显示 GridBag 定制器，请完成以下步骤：

1. 在 "Design"（设计）视图中，选择 "JFrame Form"（JFrame 窗体）。
2. 右键单击该窗体，然后选择  ``Customize Layout`` （定制布局）。
此时将打开 "Customize Layout"（定制布局）对话框，如下所示。

[.feature]
--
image::images/customizerdialog-small.png[role="left", link="images/customizerdialog.png"]
--

*注：*在本教程中，已设置了 GridBagLayout。如果使用其他窗体，请在上面的步骤 2 中右键单击该窗体，选择  ``Set Layout`` （设置布局）>  ``Grid Bag Layout`` （网格包布局）（这将启用  ``Customize Layout`` （定制布局）菜单项），然后完成该步骤。


== 高级功能

在本部分中，将使用 GridBag 定制器的高级功能，按照下面显示的目标布局重新组织  ``ContactsAdvancedInitial``  窗体组件。

image::images/targetlayout.png[]

*注：*要在 NetBeans IDE 中查看目标布局，请在 "Projects"（项目）标签中，展开  ``"Source Packages"（源包）> "tutorial"（教程）`` ，然后双击  ``ContactsAdvancedFinal.java`` 。
此时将在 GUI 构建器的 "Design"（设计）视图中打开具有目标布局的  ``ContactsAdvancedFinal``  窗体。


=== 插入新行

现有窗体的  ``Phone``  部分包含三个电话条目。要改进该部分并添加额外的标签和文本字段（例如，在  ``Cell Phone:``  和  ``Home Phone:``  之间插入 Skype 用户名），请在该位置创建一个新行，如下所示：

1. 在 "Customize Layout"（定制布局）对话框中，右键单击包含  ``Home Phone:``  信息的行标题。
2. 选择  ``Insert Row Before`` （在前面插入行）。

image::images/insertrow.png[]

此时将添加一个新行，如下图所示。

image::images/rowinserted.png[]


=== 添加新组件

要在新添加的行中添加新标签和文本字段，请完成以下步骤：

1. 右键单击新添加的行的第一个单元格。
2. 从上下文菜单中，选择  ``"Add Components"（添加组件）> "Swing Controls"（Swing 控件）> "Label"（标签）`` ，如下所示。

[.feature]
--
image::images/addcomponent-small.png[role="left", link="images/addcomponent.png"]
--

此时将在第一个单元格中突出显示  ``JLabel1`` 。



. 右键单击新添加的行的第二个单元格。


. 从上下文菜单中，选择  ``"Add Components"（添加组件）> "Swing Controls"（Swing 控件）> "Text Field"（文本字段）`` 。
此时将在第二个单元格中突出显示  ``JTextField1`` 。

image::images/highlightedtextfield.png[]

在添加组件后，必须指定这些组件的 GridBag 约束，使之与其他组件对齐。

在网格区域中选择了  ``JTextField1``  组件的情况下，在属性表单中执行以下操作：

1. 在 "Grid Width"（网格宽度）组合框中，输入  ``3`` ，然后按 Enter 键。
2. 在 "Fill"（填充）组合框中，选择  ``Horizontal`` （水平）。
3. 在 "Anchor"（锚点）组合框中，向下滚动并选择  ``Baseline`` （基线）。
4. 在 "Weight X"（X 粗细）文本字段中，输入  ``1.0`` ，然后按 Enter 键。

image::images/textfieldconstraints.png[]

在网格区域中，选择  ``JLabel1``  组件，然后在属性表单中向下滚动并选择 ``基线前导`` 以指定其  ``Anchor`` （锚点）约束。

在网格区域中同时选择  ``JLabel1``  和  ``JTextField1``  组件，单击  ``Insets`` （插入量）文本字段右侧的浏览按钮 (image::images/browsebutton.png[])。此时将显示  ``Insets`` （插入量）对话框。在  ``Top:`` （上：）文本字段中输入  ``5`` ，然后单击 "OK"（确定）。

窗体应如下所示。

image::images/constraintsset.png[]

*注：*GridBag 定制器可帮助您在布局中添加和删除组件以及更改组件的位置。要更改布局中的组件属性（如背景或文本），请使用 GUI 构建器的 "Design"（设计）窗口。

要设置  ``JLabel1``  的显示文本，请执行以下操作：

1. 单击 "Close"（关闭），以关闭 "Customize Layout"（定制布局）对话框。
2. 在 "Design"（设计）视图中，选择  ``JLabel1``  组件，然后按 F2 键（或者，从上下文菜单中选择 "Edit Text"（编辑文本））。
3. 删除选定的文本，然后输入  ``Skype:`` 。
4. 按 Enter 键。

要删除  ``JTextField1``  组件的文本，请完成以下步骤：

. 在 "Design"（设计）视图中，选择  ``JTextField1``  组件，然后按 F2 键（或者，从上下文菜单中选择 "Edit Text"（编辑文本））。
. 删除选定的文本，然后按 Enter 键。


=== 重新组织布局

GridBag 定制器允许您根据需要快速调整窗体组件的位置，节省了您的时间和精力。

要更改  ``Phone``  部分的布局以及将四个现有文本字段从一列更改为两列（各包含两个文本字段），请完成以下步骤：

1. 右键单击该窗体，然后从上下文菜单中选择  ``Customize Layout`` （定制布局）。
2. 在 "Customize Layout"（定制布局）对话框中，按住 Ctrl 键单击四个  ``JTextField``  组件将其选中。
3. 将文本字段的右边缘拖放至左侧，以使这些文本字段仅占据第二个网格列；换而言之，使它们不再占据第三个和第四个网格列。

image::images/textfieldsonecolumn.png[]

GridBag 定制器可以同时调整几个组件的大小，从而为文本字段的第二列腾出空间。



. 在窗体外部单击以取消选择调整了大小的文本字段。


. 按住 Ctrl 键单击以选择  ``Phone``  部分的所有  ``Skype:`` 、 ``Home Phone:``   ``JLabel``  和  ``JTextField``  组件。


. 将光标放在所选组件上，然后将其拖至上面两个文本字段的右侧。

image::images/movesecondcolumn.png[]

*注：*在拖动之前，请确保光标未变为双向箭头，否则，将需要调整所选组件的大小。

在移动组件后，窗体应如下所示。

image::images/extrarows.png[]

要删除多余的第 10 和 11 行（行索引分别为 9 和 10），请右键单击行标题，然后从上下文菜单中选择  ``Delete Row`` （删除行）。

 ``Phone``  部分将变得更加紧凑。

image::images/textfieldsmoved.png[]

要固定此处的第二列的间距，请执行以下操作：

1. 在网格区域中，按住 Ctrl 键单击  ``Skype:``  和  ``Home Phone:``  标签将其选中。
2. 单击  ``Insets`` （插入量）文本字段右侧的浏览按钮 (image::images/browsebutton.png[])。
此时将显示  ``Insets`` （插入量）对话框。


. 在  ``Left:`` （左侧：）文本字段中输入  ``5`` ，然后单击 "OK"（确定）。


=== 引入子容器

基于网格的布局有时会引入不必要的依赖关系，需要通过子容器进行解决。

如果单击工具栏中的 "Test Layout"（测试布局）(image::images/testlayoutbutton.png[]) 按钮并测试当前布局的水平大小可调性，则可以看到在 "Browse"、"OK" 和 "Cancel" 按钮周围创建了多余空间。

[.feature]
--
image::images/unwantedspace-small.png[role="left", link="images/unwantedspace.png"]
--

发生这种情况的原因是，第四列同时包含文本字段和按钮（这两种组件分别需要增大和减小）。您需要修改布局以使  ``Street``  和  ``City:``  文本字段占据  ``Browse``  按钮周围的额外空间。当前布局确保了  ``Street:``  和  ``City:``  文本字段右边缘的垂直位置与  ``Home Phone:``  文本字段左边缘相同。要使这些位置没有关联，请完成以下步骤：

1. 按住 Ctrl 键单击  ``Street:``  文本字段及其右侧的  ``Browse``  按钮将其选中。
2. 右键单击所选内容，然后从上下文菜单中选择  ``Enclose in Container`` （包含在容器中）。

[.feature]
--
image::images/enclose-small.png[role="left", link="images/enclose.png"]
--

在将组件包含在子容器中后， ``Home Phone:``  标签和文本字段之间的边界不再影响  ``Street``  文本字段和按钮之间的边界。

*注：* ``Enclose in Container`` （包含在容器中）操作将在选定组件占据的单元格中创建一个新的子容器。它将选定组件移到新引入的容器中，但保留其相对位置和其他布局约束。

对于  ``City:``  文本字段及其右侧的  ``Browse``  按钮，重复上面列出的两个步骤，以便将其包含在子容器中，如下所示。

image::images/enclosecity.png[]

现在，您希望按如下方式删除  ``OK``  和  ``Cancel``  按钮周围的多余空间：

1. 单击 "Close"（关闭）取消选择包含在子容器中的组件，右键单击窗体，然后从上下文菜单中选择  ``Customize Layout`` （定制布局）。
2. 按住 Ctrl 键单击窗体底部的  ``OK``  和  ``Cancel``  按钮将其选中。
3. 右键单击所选内容，然后从上下文菜单中选择  ``Enclose in Container`` （包含在容器中）。
此时将为这些按钮创建一个新的子容器。

image::images/subcontainerbuttons.png[]

*注：*无法调整子容器中的任何组件的大小。因此，这些组件将彼此相邻放在容器的中心位置（这是默认锚定方式）。

要更改整个子容器的锚定方式，请完成以下步骤：

1. 请确保选中了带有  ``OK``  和  ``Cancel``  按钮的子容器，然后单击  ``Anchor`` （锚点）组合框右侧的箭头按钮 (image::images/arrowbutton.png[])。
2. 向下滚动并从列表中选择  ``Line End`` （行尾）。

image::images/subcontainerlineend.png[]

布局效果看起来很好，但包含  ``OK``  和  ``Cancel``  按钮的子容器仅占据最后一行中的最后两个单元格。
如果  ``OK``  和  ``Cancel``  按钮变宽（例如，在翻译为不同语言期间），则这些按钮会将  ``Work Phone:``  和  ``Cell Phone:``  文本字段的右边缘向后推。
为避免出现这种潜在的问题，并使子容器占据底部行中的所有单元格，请选择该子容器，然后将其左边框拖至行的开头。

image::images/subcontainerresized.png[]

子容器将占据底部行的所有单元格。


=== 在容器之间导航

要在子容器中添加组件（例如，在现有  ``OK``  和  ``Cancel``  按钮的基础上添加  ``Help``  按钮），您需要在编辑子容器布局之前从主容器切换到子容器。

完成下面列出的步骤，在现有子容器中添加一个按钮：

1. 单击包含  ``OK``  和  ``Cancel``  按钮的子容器将其选中。
2. 右键单击该容器以显示上下文菜单，然后从该菜单中选择  ``Design This Container`` （设计此容器）。

[.feature]
--
image::images/designsubcontainer-small.png[role="left", link="images/designsubcontainer.png"]
--



. 右键单击第二列的标题，然后从上下文菜单中选择  ``Insert Column After`` （在后面插入列）。
此时将显示新按钮的空单元格。

[.feature]
--
image::images/emptycell-small.png[role="left", link="images/emptycell.png"]
--



. 在新创建的单元格内右键单击，然后从上下文菜单中选择  ``Add Component`` （添加组件）>  ``Swing Controls`` （Swing 控件）>  ``Button`` （按钮）。
此时将添加一个新的  ``jButton1``  按钮。

[.feature]
--
image::images/newbutton-small.png[role="left", link="images/newbutton.png"]
--



. 单击属性定制器中的 "Baseline-Related Anchor"（与基线相关的锚点）按钮 (image::images/baselineanchor.png[])，将新按钮与行中的两个现有按钮对齐。


. 单击 "Insets"（插入量）文本字段右侧的浏览按钮 (image::images/browsebutton.png[])。此时将显示 "Insets"（插入量）对话框。在 "Top:"（上：）文本字段中输入 5，然后单击 "OK"（确定）。


. 要立即查看主容器布局的外观，请右键单击设计的子容器，然后从上下文菜单中选择  ``Design Parent Container`` （设计父容器）。

image::images/designparentcontainer.png[]

*注：*如果右键单击这些按钮，则不会显示上下文菜单。

布局设计现已完成。
只剩下与容器布局无关的最终更改。
要重命名该按钮，请完成以下步骤：

1. 单击 "Close"（关闭），以关闭 "Customize Layout"（定制布局）对话框。
2. 在 "Design"（设计）视图中，单击  ``jButton1``  组件，然后按 F2 键（或者，从上下文菜单中选择 "Edit Text"（编辑文本））。
3. 删除选定的文本，然后输入  ``Help`` 。
4. 按 Enter 键。

image::images/finallayout.png[]


== 小结

在本教程中，您通过添加新组件、插入行等操作修改了现有窗体。在设计布局时，您了解了如何使用 GridBag 定制器的高级功能重新组织窗体布局。

转至link:../java/gbcustomizer-basic.html[+使用 GridBag 定制器设计基本 Java 窗体+]

<<top,返回页首>>

link:/about/contact_form.html?to=3&subject=Feedback:%20Designing%20an%20Advanced%20Java%20Form%20Using%20the%20GridBag%20Customizer[+发送有关此教程的反馈意见+]



== 另请参见

现在，您已完成了“使用 GridBag 定制器设计高级 Java 窗体”教程。有关向所创建的 GUI 中添加功能的信息，请参见：

* link:gui-functionality.html[+构建 GUI 应用程序简介+]
* link:gui-image-display.html[+在 GUI 应用程序中处理图像+]
* link:http://wiki.netbeans.org/NetBeansUserFAQ#GUI_Editor_.28Matisse.29[+GUI 构建器常见问题解答+]
* link:../../trails/matisse.html[+Java GUI 应用程序学习资源+]
* link:http://www.oracle.com/pls/topic/lookup?ctx=nb8000&id=NBDAG920[+使用 NetBeans IDE 开发应用程序+]中的_实现 Java GUI_

<<top,返回页首>>

