博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入学习GridBagLayout
阅读量:7240 次
发布时间:2019-06-29

本文共 10879 字,大约阅读时间需要 36 分钟。

  试着用用你会发现其实GridBagLayout真的能解决几乎所有界面布局的问题,窗口大小的随意改变也不会影响到整体布局,更重要的是它可以实现任何你想要的布局设计,只要你做到更有计划和更有耐心一点就行了。对于简单的程序使用Boborderlayout和Gridlayout就绰绰有余了, 但如果要把程序提到实际应用上你就得考虑使用GridBagLayout。当然, 做复杂的应用程序时,一开始就使用GridBagLayout就会更有效率。一旦你决定使用GridBagLayout,接下来一步便是要找一些纸和铅笔,只有你准确知道你的界面看上去需要成什么样子,你就可以敲键盘。这就是说,你应该在编码之前进行妥善规划。

  GridBagLayout从它的名字中你也可以猜到,它同GridLayout一样,在容器中以网格形式来管理组件.但GridBagLayout功能要来得强大得多.

1、GridBagLayout管理的所有行和列都可以是大小不同的.
2、GridLayout把每个组件限制到一个单元格,而GridBagLayout并不这样:组件在容器中可以占据任意大小的矩形区域,GridBagLayout通常由一个专用类来对他布局行为进行约束,该类叫GridBagConstraints.其中的所有成员都是public的, 因此要学好如何使用GridBagLayout首先要了解有那些约束变量,以及如何设置这些约束变量.以下是GridBagConstraints的公有成员变量:

构造函数:

    GirdBagLayout()建立一个新的GridBagLayout管理器。
    GridBagConstraints()建立一个新的GridBagConstraints对象。
    GridBagConstraints(int gridx,int gridy,
                                   int gridwidth,int gridheight,
                                   double weightx,double weighty,
                                   int anchor,int fill, Insets insets,
                                   int ipadx,int ipady)建立一个新的GridBagConstraints对象,并指定其参数的值。
参数说明:
 gridx,gridy    ——    设置组件的位置,
                       gridx设置为GridBagConstraints.RELATIVE代表此组件位于之前所加入组件的右边。
                       gridy设置为GridBagConstraints.RELATIVE代表此组件位于以前所加入组件的下面。
                      建议定义出gridx,gridy的位置以便以后维护程序。gridx=0,gridy=0时放在0行0列。

 gridwidth,gridheight    ——    用来设置组件所占的单位长度与高度,默认值皆为1。

                           你可以使用GridBagConstraints.REMAINDER常量,代表此组件为此行或此列的最后一个组件,而且会占据所有剩余的空间。

 weightx,weighty    ——    用来设置窗口变大时,各组件跟着变大的比例。

                        当数字越大,表示组件能得到更多的空间,默认值皆为0。
 anchor    ——    当组件空间大于组件本身时,要将组件置于何处。
                  有CENTER(默认值)、NORTH、NORTHEAST、EAST、SOUTHEAST、WEST、NORTHWEST选择。
 insets    ——    设置组件之间彼此的间距。
                它有四个参数,分别是上,左,下,右,默认为(0,0,0,0)。
ipadx,ipady    ——    设置组件间距,默认值为0。

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

import java.awt.*;import java.awt.event.*;import javax.swing.*;public class GridBagWindow extends JFrame {  private JButton searchBtn;  private JComboBox modeCombo;  private JLabel tagLbl;  private JLabel tagModeLbl;  private JLabel previewLbl;  private JTable resTable;  private JTextField tagTxt; public GridBagWindow() {   Container contentPane = getContentPane();   GridBagLayout gridbag = new GridBagLayout();   contentPane.setLayout(gridbag);   GridBagConstraints c = new GridBagConstraints();   //setting a default constraint value   c.fill =GridBagConstraints.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);  addWindowListener(new WindowAdapter() {    public void windowClosing(WindowEvent e) {     System.exit(0);    }  });} public static void main(String args[]) {  GridBagWindow window = new GridBagWindow();  window.setTitle("GridBagWindow");  window.pack();  window.setVisible(true); }}

 

构造方法前的代码都不是很特殊,都是一些相当标准的import和变量定义。但是进入构造方法后,事情就变得有趣了。

Container contentPane = getContentPane();

GridBagLayout gridbag = new GridBagLayout();

contentPane.setLayout(gridbag);

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

GridBagConstraints c = new GridBagConstraints();

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

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

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

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

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

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

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

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

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);

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

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

 最近正在修改《公交线路查询系统》,做系统的时候都是用NULL布局,由于NULL布局调用windows系统的API,所以生成的程序无法在其他平台上应用,而且如果控件的数量很多,管理起来也比较麻烦,最近我发现一个非常强大的布局模式 :GridBagConstraints布局,先发一个实例:

gridx = 2; // X2
gridy = 0; // Y0
gridwidth = 1; // 横占一个单元格
gridheight = 1; // 列占一个单元格
weightx = 0.0; // 当窗口放大时,长度不变
weighty = 0.0; // 当窗口放大时,高度不变
anchor = GridBagConstraints.NORTH; // 当组件没有空间大时,使组件处在北部
fill = GridBagConstraints.BOTH; // 当格子有剩余空间时,填充空间
insert = new Insets(0, 0, 0, 0); // 组件彼此的间距
ipadx = 0; // 组件内部填充空间,即给组件的最小宽度添加多大的空间
ipady = 0; // 组件内部填充空间,即给组件的最小高度添加多大的空间
new GridBagConstraints(gridx, gridy, gridwidth, gridheight, weightx, weighty, anchor, fill, insert, ipadx, ipady);
GridBagLayout之变态玩法:
很多人抱怨GridBagLayout没有XYLayout布局灵活,但是做为一个专业程序,所有组件必须随着窗口大小改变而改变。其次,当仅仅简单使用XYLayout时,需要包含一个大库,对于一些场合这些多余的类超出了可接受范围(例如Applet应用)
拿一个比较简单的界面来作介绍 
1。首先建立一个JFrame,设定它的Layout为XYLayout 
2。在其上堆上控件,对齐好位置,否则转换时会有较大调整 
3。完成创建控件后,设置Layout为GridBagLayout,这时所有控件基本保持原位,待下一步做精细调整 
4。选择一个控件,点击右边属性栏的"constraints" 对应的调整按钮,弹出最重要的属性调整界面 
5。将所有边界和空白去掉,同时Grid大小也暂时去掉,因为这些边距会影响我们的调整 
6。设置需要扩展的行和列 
7。粗轮廓完成后,可以设置组件边距进行精细调整了 
8。精细调整完成,运行调试

以下是GridBagLayout的详解:
虽说GridBagLayout和GridLayout只有一点差别,它
的作用却是出奇的大。这是因为GridBagLayout一改其他的外观管理器的死板
模样,具有很多的灵活性。它不再像其他的外观管理器那样,使得各个组件
的大小都一样。 GridBagLayout通过类GridBagConstraints的帮助,按照
设计的意图,改变组件的大小,把它们摆在设计者希望摆放的位置上。
在GridBagLayout中,每个组件都有一个GridBagConstraints 
对象来给出它的大小和摆放位置。我们在使用GridBagLayout的时候,最重 
要的就是学会使用这个类GridBagConstraints的使用方法,学会如何设置组
件的大小、位置等限制条件。
我们先看一个用GridBagLayout外观管理器生成的窗口

图14.8程序14.5的执行结果
这个窗口里面的几个按钮有的大、有的小,其大小、位
置均不同,没有一定的规律可循,这即是发挥了GridBagLayout外观管理器
的灵活性。生成此窗口的程序为:
程序14.5
  importjava.awt.*;
      //输入所有的java.awt 类
  publicclasswindow7extendsjava.applet.Applet
  {
   publicvoidinit() {
    resize(300,100);//设置窗口的大小
    GridBagConstraintsgbc=new GridBagConstraints(
);//使用类GridBagConstriants
    setLayout(newGridBagLayout());//设定外观
管理器为 GridBagLayout外观管理器 
    gbc.fill =GridBagConstraints.BOTH;//★
所有的按钮都会把分配的剩余空间填满
    gbc.gridwidth=1;//★设置第一个按钮的大
    gbc.gridheight=1;// ★
    ButtonButton1=newButton("东 ");
    ((GridBagLayout)getLayout( )).setConstraints(Button1,gbc);
     add(Button1);
    gbc.gridwidth= GridBagConstraints.REMAINDER;
//★第二个按钮填满整行空间
    ButtonButton2=newButton("西 ");
    ((GridBagLayout)getLayout( )).setConstraints(Button2,gbc);
     add(Button2);
    gbc.gridheight=4;//设置第三个按钮的大
    gbc.gridwidth= 1;
    ButtonButton3=newButton("南 ");
    ((GridBagLayout)getLayout( )).setConstraints(Button3,gbc);
     add(Button3);
    gbc.gridheight=2;//设置第四个按钮的大
    gbc.gridwidth= 2;//GridBagConstraints.REMAINDER;
     ButtonButton4=newButton("北");
     ((GridBagLayout)getLayout( )).setConstraints(Button4,gbc);
     add(Button4);
    gbc.gridwidth= GridBagConstraints.REMAINDER;
    Button Button5=newButton("中");
     ((GridBagLayout)getLayout( )).setConstraints(Button5,gbc);
     add(Button5);
    gbc.insets=new Insets(5,6,7,8);//★设置第五个按钮的位置
    ButtonButton6=newButton("好酒在张弓");
    ((GridBagLayout)getLayout( )).setConstraints(Button6,gbc);
     add(Button6);
           }
  }
  ★注释:程序14.5里面有星号的语句都将做详细的解释
下面就详细地解释一下程序14.5,通过对这个小程序的分析可以从中了解GridBagLayout外观管理器的工作原理和工作方法。
  GridBagLayout外观管理器实际上是根据类GridBagConstraints所给
出的条件限制以及组件本身的一向特性条件(例如每个组件程序允许的最小
尺寸),来决定各个组件的外观的。 
让我们把程序14.5之中出现的新鲜的语句一条一条地看个明白吧:
1.gbc.fill=GridBagConstraints.BOTH;
每个组件有一定的原始大小,例如在类FlowLayout外
观管理器的管理之下显示的就都是组件的本身原始大小。如果我们分配给一
个组件的空间比它原本所需要的空间大时,就需要一定的方式方法来决定如
何处理这一部分多余的空间。这时就用到了fill值。Java根据人们给这个
fill设定的值来决定如何处理比组件原始空间大的那部分空间。 
fill可以取四种不同的值,它们分别代表了四种不同
的剩余空间处理方式:
GridBagConstraints.NONE
  不必理睬剩余空间的存在,让它空着好了。
GridBagConstraints.BOTH
  不让一点剩余空间存在,改变组件的大小,让它填
满分配给它的整个空间。
GridBagConstraints.HORIZONTAL
  调整组件的大小,把水平方向的空间填满。
GridBagConstraints.VERTICAL
  调整组件的大小,把垂直方向的空间填满,让水平
方向的空间空着吧。
2.gbc.gridwidth=1;和 gbc.gridheight=1;
这两句话像是一对孪生兄弟,应该同时给以同样的重视
。它们一个负责组件的水平宽度(gridwidth),一个负责组件的垂直高度
(gridheight )。由此我们可以知道,组件的大小是可以变化的。
组件的形状是不能改变的,永远是矩形的。
  好了,这两条语句的意义很简单,就讲到这里吧。
  喂!等一等,我看到下面有一条语句是:
    gbc.gridwidth= GridBagConstraints.REMAINDER;
这是什么意思?
怎么gridwidth的值不是一个数,而是“ GridBagConstraints.REMAINDER
”?
原来,这是Java精心为大家设计的一个特别有用的变
量,使用它就可以通知外观管理器让组件占据本行的所有剩余空间,而不必
去计算宽度值是多少,很自动化。
3.gbc.insets=newInsets(5,6,7,8);
这条语句里面提到了两个拼写几乎完全相同的词:insets
和 Insets,虽然只相差一个字母:一个是大写I,一个是小写i,但是它
们代表的意义可大不相同。
Insets是AWT里面一个类的名字,代表着类Insets,它的用途是用来定义组件容器周围的空间大小,其中带有四个参数:
Insets(第一个参数,第二个参数,第三个参数,第
四个参数 )
第一个参数代表距上面有几个点的空白,第二个参数代
表距左边有几个点的空白,第三个参数代表距下边有几个点的空白区域,第
四个参数代表距右边留几个点的空白区域。
  形象一点的表示如图 14.9:

图14.9参数的设定顺序
insets是类GridBagConstraints的一个限定条件。
insets和Insets既然起的名字相同,两者之间也一
定有相同之处,它们的相似之处就在于它们的用法和用途。insets用来设置
一个组件和其他的组件之间的距离的。所以在上面程序里的按钮和其他的按
钮不同,它和其他的按钮之间都有一定的距离,而不是和其他的按钮挨在一
起。
总之,使用外观管理器给我们带来了许多的方便之处,
使得我们可以轻轻松松地完成各种窗口的外观处理工作。
使用外观管理器除了使得程序设计变得方便以外,还
使得程序变得容易在各种不同的窗口环境下运行,从而协助实现了Java的多
平台之梦。
    小结:
学会使用各种各样的外观管理器会带来事半功倍的编
程效果。
这一章里新学习的类有:
BorderLayout,CardLayout,FlowLayout,GridLayot 
,ridBagLayout,GridBagConstraints和Insets。
类GridBagLayout生成的外观管理器是最具有灵活性
的外观管理器。
类GridBagLayout需要通过类GridBagconstraints
来实现对程序窗口外观的管理。

转载地址:http://puybm.baihongyu.com/

你可能感兴趣的文章
Ubuntu14.04下沙盒数据导入到 Neo4j 数据库(图文详解)
查看>>
如何设断点????-----使用WinDbg调试SQL Server查询
查看>>
sql 高性能存储过程分页
查看>>
Java -- 异常的捕获及处理 -- 异常类的继承结构
查看>>
外链建设的主要门户渠道
查看>>
sqlserver如何添加全文索引
查看>>
UVALive - 4960 Sensor network(生成树+LCA)
查看>>
IIS与asp.net管道
查看>>
poj 2585 Window Pains 暴力枚举排列
查看>>
[ACM] ZOJ 3725 Painting Storages (DP计数+组合)
查看>>
Java:String和Date、Timestamp之间的转换
查看>>
Android自己定义实现循环滚轮控件WheelView
查看>>
新eclipse 打开就版本的工作空间提示:
查看>>
1250 Fibonacci数列
查看>>
activiti自己定义流程之整合(三):整合自己定义表单创建模型
查看>>
Tomcat 文件夹结构
查看>>
myeclipse集成maven
查看>>
数据结构精要------冒泡与直接排序算法
查看>>
python中将图片从客户端(client)推到(POST)到服务器端(server)的方法
查看>>
落地生根两周年,微软Azure进入2.0时代
查看>>