zoukankan      html  css  js  c++  java
  • 深入学习GridBagLayout

      试着用用你会发现其实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。精细调整完成,运行调试

    JAVA布局模式:GridBagConstraints终极技巧



    以下是GridBagLayout的详解:
    虽说GridBagLayout和GridLayout只有一点差别,它
    的作用却是出奇的大。这是因为GridBagLayout一改其他的外观管理器的死板
    模样,具有很多的灵活性。它不再像其他的外观管理器那样,使得各个组件
    的大小都一样。 GridBagLayout通过类GridBagConstraints的帮助,按照
    设计的意图,改变组件的大小,把它们摆在设计者希望摆放的位置上。

    在GridBagLayout中,每个组件都有一个GridBagConstraints 
    对象来给出它的大小和摆放位置。我们在使用GridBagLayout的时候,最重 
    要的就是学会使用这个类GridBagConstraints的使用方法,学会如何设置组
    件的大小、位置等限制条件。

    我们先看一个用GridBagLayout外观管理器生成的窗口

    JAVA布局模式:GridBagConstraints终极技巧



    图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:

    JAVA布局模式:GridBagConstraints终极技巧



    图14.9参数的设定顺序

    insets是类GridBagConstraints的一个限定条件。

    insets和Insets既然起的名字相同,两者之间也一
    定有相同之处,它们的相似之处就在于它们的用法和用途。insets用来设置
    一个组件和其他的组件之间的距离的。所以在上面程序里的按钮和其他的按
    钮不同,它和其他的按钮之间都有一定的距离,而不是和其他的按钮挨在一
    起。

    总之,使用外观管理器给我们带来了许多的方便之处,
    使得我们可以轻轻松松地完成各种窗口的外观处理工作。

    使用外观管理器除了使得程序设计变得方便以外,还
    使得程序变得容易在各种不同的窗口环境下运行,从而协助实现了Java的多
    平台之梦。

        小结:

    学会使用各种各样的外观管理器会带来事半功倍的编
    程效果。

    这一章里新学习的类有:

    BorderLayout,CardLayout,FlowLayout,GridLayot 
    ,ridBagLayout,GridBagConstraints和Insets。

    类GridBagLayout生成的外观管理器是最具有灵活性
    的外观管理器。

    类GridBagLayout需要通过类GridBagconstraints
    来实现对程序窗口外观的管理。

  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/renyuan/p/2723809.html
Copyright © 2011-2022 走看看