深入学习GridBagLayout

原创 2007年09月14日 11:16:00

利用Java来创建图形用户界面,最苦恼的事情莫过于选择用哪种布局管理器了。

许多应用程序使用嵌套的Border和GridLayout来进行布局, 但是得到的结果要么变得太死板、太嵌套了以至于都无法工作了,要么就是窗口在变化的时候布局太不合理了,这样往往解决方法只有启用多个窗口,还有要么就是固定窗口的大小不允许改变。

无论是那种选择都不是很好,因为它使得应用程序从界面看上去不太美观,同样也会让应用程序的界面在使用上受到很多的限制。

但还好有一个工具能够解决所有的这些问题—那就是GridBagLayout。可惜很多人因为看到这个布局管理器感觉它太复杂了认为很难而不敢去学习,他们一直都不愿意尝试下去使用这个布局管理器。

试着用用你会发现其实GridBagLayout真的能解决几乎所有界面布局的问题,窗口大小的随意改变也不会影响到整体布局,更重要的是它可以实现任何你想要的布局设计,只要你做到更有计划些和更有耐心一点就行了。

三思而后行

GridBagLayout 不是用于简单的示例程序界面。使用GridBagLayout搭建界面就像是在起居室中搭脚手架清除画钩一样。

对于简单的程序使用Boborderlayout和Gridlayout就绰绰有余了, 但如果要把程序提到实际应用上你就得考虑使用GridBagLayout。当然, 做复杂的应用程序时,一开始就使用GridBagLayout就会更有效率。

一旦你决定使用GridBagLayout,接下来一步便是要找一些纸和铅笔,只有你准确知道你的界面看上去需要成什么样子,你就可以敲键盘。这就是说,你应该在编码之前进行妥善规划。

下面将介绍一个很小的应用程序来帮助我们学习GridBagLayout,这个例子是从一个Flickr RSS fead中显示一系列照片, 最后的界面就像下面这样:

JAVA:深入学习GridBagLayout

下面的是这个界面的一个原始草图:

JAVA:深入学习GridBagLayout

正如你所看到的,最终的结果看上去和计划的想法完全一样。

你应该能看到在草图里有一些线,这些线是用来把总界面分成若干行和列的,这样你就很清楚每一个组件放置的格子位置。这就是GridBagLayout里"格"的那一部分,而图上的数字就是格的号码。

在某种意义上说, 我们可以把GridBagLayout想象成为早些年的HTML3和4,它们都是基于表的布局,Grid的概念就类似rowspan和colspan的意思,只不过换了个名字罢了。

随着我们的界面和表格的设置完成,是时候该进行界面布局并开始写代码了。

工作过程

这一节我假定你已经了解了基本的窗口和组件创建知识。

通过这篇文章我们最终能在一个frame中布局组件,我们将在以后的文章对界面进行改进使它更适用。

因此,为了了解这整个工作的过程,我们列出了所有的目标代码。

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class GridBagWindowGridBagWindow extends JFrame {

private JButton searchBtn;

private JComboBox modeCombo;

private JLabel tagLbl;

private JLabel tagModeLbl;

private JLabel previewLbl;

private JTable resTable;

private JTextField tagTxt;

public GridBagWindowGridBagWindow() {

Container contentPane = getContentPanegetContentPane();

GridBagLayout gridbag = new GridBagLayout();

contentPane.setLayout(gridbag);

GridBagConstraintsGridBagConstraints c = new GridBagConstraintsGridBagConstraints();

//setting a default constraint value

c.fill = GridBagConstraintsGridBagConstraints.HORIZONTAL;

tagLbl = new JLabel("Tags");

c.gridx = 0; //x grid position

c.gridy = 0; //y grid position

gridbag.setConstraints(tagLbl, c); //associate the label with a constraint object

contentPane.add(tagLbl); //add it to content pane

tagModeLbl = new JLabel("Tag Mode");

c.gridx = 0;

c.gridy = 1;

gridbag.setConstraints(tagModeLbl, c);

contentPane.add(tagModeLbl);

tagTxt = new JTextField("plinth");

c.gridx = 1;

c.gridy = 0;

c.gridwidth = 2;

gridbag.setConstraints(tagTxt, c);

contentPane.add(tagTxt);

String[] options = {"all", "any"};

modeCombo = new JComboBox(options);

c.gridx = 1;

c.gridy = 1;

c.gridwidth = 1;

gridbag.setConstraints(modeCombo, c);

contentPane.add(modeCombo);

searchBtn = new JButton("Search");

c.gridx = 1;

c.gridy = 2;

gridbag.setConstraints(searchBtn, c);

contentPane.add(searchBtn);

resTable = new JTable(5,3);

c.gridx = 0;

c.gridy = 3;

c.gridwidth = 3;

gridbag.setConstraints(resTable, c);

contentPane.add(resTable);

previewLbl = new JLabel("Preview goes here");

c.gridx = 0;

c.gridy = 4;

gridbag.setConstraints(previewLbl, c);

contentPane.add(previewLbl);

addWindowListeneraddWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

}

public static void main(String args[]) {

GridBagWindowGridBagWindow window = new GridBagWindowGridBagWindow();

window.setTitle("GridBagWindowGridBagWindow");

window.pack();

window.setVisible(true);

}

}

构造方法前的代码都不是很特殊,都是一些相当标准的import和变量定义。

但是进入构造方法后,事情就变得有趣了。

Container contentPane = getContentPanegetContentPane();

GridBagLayout gridbag = new GridBagLayout();

contentPane.setLayout(gridbag);

我们以GridBagWindow的内容面板作为开始来创建一个GridBagLayout对象,准确地说,这个方法与过去我们所创建GridLayout对象和BorderLayout对象的方法是一样的。那么,现在我们就开始来设置GridBagLayout对象使它作为内容面板的布局。

GridBagConstraintsGridBagConstraints c = new GridBagConstraintsGridBagConstraints();

然后我要提到这整个进程中的一个独特的对象,那就是GridBagConstraintsGridBagConstraints。这个对象在GridBagLayout中控制所有被安置在其中组件的约束。为了把一个组件增加到你的GridBagLayout中去,你首先必须将它与一个GridBagConstraintsGridBagConstraints对象建立连接。

GridBagConstraintsGridBagConstraints可以从11个方面来进行控制和操纵,也可以给你提供一些帮助。这些内容是:

  • Gridx——组件的横向坐标
  • Girdy——组件的纵向坐标
  • Gridwidth——组件的横向宽度,也就是指组件占用的列数,这与HTML的colspan类似
  • Gridheight——组件的纵向长度,也就是指组件占用的行数,这与HTML的rowspan类似
  • Weightx——指行的权重,告诉布局管理器如何分配额外的水平空间
  • Weighty——指列的权重,告诉布局管理器如何分配额外的垂直空间
  • Anchor——告诉布局管理器组件在表格空间中的位置
  • Fill——如果显示区域比组件的区域大的时候,可以用来控制组件的行为。控制组件是垂直填充,还是水平填充,或者两个方向一起填充
  • Insets——指组件与表格空间四周边缘的空白区域的大小
  • Ipadx—— 组件间的横向间距,组件的宽度就是这个组件的最小宽度加上ipadx值
  • ipady—— 组件间的纵向间距,组件的高度就是这个组件的最小高度加上ipady值

可能对于一个组件的每一个实例你都需要为它建立一个单独的GridBagConstraintsGridBagConstraints;然而,这种方法我们并不推荐使用。最好的方法是,当你调用它的时候把对象设置为默认值,然后针对于每一个组件改变其相应的域。

这个方法具有通用性,因为在一些域中,比如insets、padx、pady和fill这些域,对于每一个组件来说一般都是相同的,因此这样对一个域进行设置就会更轻松了,也能更轻松的在另外的组件中改变某些域的值。

如果在改变了某些域值之后,你想回到原始的域值的话,你应该在增加下一个组件之前进行改变。这种方法使你更容易明白你正在修改的内容,也能使你更容易明白在一连串对象中的这11个参数的作用。

也许你现在对这些内容还是一知半解,不过事实上一旦你理解了GridBagConstraintsGridBagConstraints,值得安慰的是你以后做再困难的工作都会游刃有余了。

所以,如果我们已经明白了GridBagConstraintsGridBagConstraints的详细用法了,那么现在就让我们来看看在实际应用中应该如何来实现它:

tagLbl = new JLabel("Tags");

c.gridx = 0; //x grid position

c.gridy = 0; //y grid position

gridbag.setConstraints(tagLbl, c); //设置标签的限制

contentPane.add(tagLbl); //增加到内容面板

我们所做的是示例我们的标签、分配给它一个格位置,将它与一个约束对象联系起来并把它增加到我们的内容面板中。

tagModeLbl = new JLabel("Tag Mode");

c.gridx = 0;

c.gridy = 1;

gridbag.setConstraints(tagModeLbl, c);

contentPane.add(tagModeLbl);

请注意,虽然我们已经在我们的约束对象中把gridx的值设置为0,但是在这里我们仍然要对它进行重新设置——这样做没有其它原因,只是为了增加可读性。

下面,我们增加一个文本域以便能存储我们希望能搜索到的关键字,再增加一个组合框以便用来搜索多个关键字。除了我们希望的文本域有两列之外,这个概念其他的方面都与上面所说的是相同的,所以,我们需要在增加组合框之前重新设置文本域的值。

tagTxt = new JTextField("plinth");

c.gridx = 1;

c.gridy = 0;

c.gridwidth = 2;

gridbag.setConstraints(tagTxt, c);

contentPane.add(tagTxt);

String[] options = {"all", "any"};

modeCombo = new JComboBox(options);

c.gridx = 1;

c.gridy = 1;

c.gridwidth = 1;

gridbag.setConstraints(modeCombo, c);

contentPane.add(modeCombo);

做了这些之后,我们再在内容面板中增加一些其余的简单组件,这时候我们就能够浏览它了;其余的代码应该不会出现任何问题了。

到这个阶段,我们应该已经得到了一个类似于我们先前所设计的界面了。

进一步学习

当然,界面不是智能的。重新设置窗口的大小,看看将会发生些什么事情。为什么它会那样呢?那是因为我们设置了约束对象的weightx、weighty和fill的值。

关于其他类似的一些内容我们将在后面的章节中进行介绍,但是如果你希望能自己试试的话,参考GridBigLayoutGridBagConstraintsGridBagConstraintsAPI文档会对扩充你的知识提供很好的帮助。

 

Swing超基础学习总结——3、复杂布局:GridBagLayout

据说是最复杂的布局也是最实用的一个布局GridBagLayout 使用步骤 案例GridBagLayout使用步骤①建立容器(例如JFrame)并设置布局方式:JFrame frame = new J...
  • zhengyikuangge
  • zhengyikuangge
  • 2016年08月28日 08:02
  • 872

java中的gridbaglayout的简单用法

要知道gridwidth、gridheight表示组件所占据的行数,可以取值int、GridBagConstraints.RELATIVE(取这个值表示这是这一行(或列)的倒数第二个组件)、GridB...
  • yr_fly
  • yr_fly
  • 2016年10月28日 21:46
  • 2285

Java_GUI中GridBagLayout布局使用详解

GridBagLayout以表格形式布置容器内的组件, 将每个组件放置在每个单元格内,而一个单元格可以跨越多个单元格合并成一个单元格,即多个单元格可以组合成一个单元格,从而实现组件的自由布局。 每一个...
  • update_java
  • update_java
  • 2015年07月12日 18:28
  • 1696

[疯狂Java笔记]AWT:GridLayout网格布局、GridBagLayout网格袋布局

1. GridLayout——网格布局:    1) 网格顾名思义就是纵横分割大小一样的格网,每个格子都是矩形的,且大小相等,每个格子只能存放一个组件;    2) 构造器:最大的特点就是必须指定...
  • Lirx_Tech
  • Lirx_Tech
  • 2016年03月02日 12:59
  • 2647

GridBagLayout布局管理器应用详解

package test; import java.awt.Color; import java.awt.Container; import java.awt.GridBagLayout; ...
  • dreamoftch
  • dreamoftch
  • 2013年10月11日 13:52
  • 442

swing入门教程(五) swing其他重要概念

——关于Swing 布局、事件和模型。 既然您已经知道了大多数(肯定不是全部)可以用来制作 UI 的组件,那么就必须实际用它们做些什么。您不能只是随意地把它们放在屏幕上,然后就指望它们立即就能工...
  • alli0968
  • alli0968
  • 2016年02月05日 10:42
  • 1147

GridBagLayout的使用方法

Java 的布局管理器       GridBagLayout是java里面最重要的布局管理器之一,可以做出很复杂的布局,可以说GridBagLayout是必须要学好的的, GridBa...
  • txl444363699
  • txl444363699
  • 2015年02月09日 22:35
  • 309

GridBagLayout网格包布局管理器

GridBagLayout            灵活也难以掌控的布局管理器,每个 GridBagLayout 对象维持一个动态的矩形单元网格,每个组件占用一个或多个这样的单元,该单元被称为显示区...
  • qq_29481375
  • qq_29481375
  • 2016年04月03日 08:16
  • 956

GridBagLayout布局管理器学习总结

最近工作需要为一个java控制台的小程序,添加界面。所以需要学习Swing的知识。 package Study; import java.awt.Component; import java.aw...
  • q766973278
  • q766973278
  • 2015年11月17日 10:20
  • 83

GridBagLayout布局管理器的应用

GridBagLayout布局管理器比较复杂,参数也比较多,参数是  newGridBagConstraints(gridx,gridy,gridwidth,gridheight,weightx,...
  • luoww1
  • luoww1
  • 2013年08月21日 15:18
  • 716
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入学习GridBagLayout
举报原因:
原因补充:

(最多只允许输入30个字)