GridBagLayout 梗概

来源:互联网 发布:网络犯罪调查分集介绍 编辑:程序博客网 时间:2024/04/30 11:04

        我想应该好多人都和我一样吧,对GridBagLayout莫名的抵触。呵呵,我想可能是由于我们一接触Swing的时候就被告知,“恩,GridBagLayout是布局器中最复杂的一种,如果你用到了GridBagLayout,那么这说明你就要使用管理布局的工具了。”什么意思,如果用不到GridBagLayout,不用学了,如果用到了GridBagLayout呢,那也不用学,因为这时你就要用布局工具了。
        其实未必,GridBagLayout 有11个参数,但是如果搞懂了各个的意思,其实这种布局并不难,而且这种布局作出的效果也是最好的。

        好了,学习了下GridBagLayout,写下来,希望可以对大家有点帮助。

        文章翻译自:Manning - Java Swing 2nd Edition (2005) 

 

4.1.8 GridBagLayout

alass java.awt.GridBagLayout, class java.awt.GridBagConstraints

这种Layoutconstraints-based GridLayout。这种Layout将容器的空间分成相等的矩形的小块(就像是墙上的砖块一样),然后把每个组件放到一个或者多个小矩形中(跨越几个小矩形 gridwidth, gridheight控制;当然小块在容器改变大小时,所改变的比例则由weightx, weighty来控制;组件在一个或者多个小块内部是如何放置则由ancher, fill来控制)。你要为每个组件都创建一个GridBagConstraints对象,填充这个对象的所有属性,然后让这个GridBagConstraints来告知GridBagLayout应该如何放置这个组件,以及告知GridBagLayout当容器大小改变时,如何让这个组件相应的进行变化。

如果在容器大小改变时对组件的大小位置等的变化没有特殊的要求,那么GridBagLayout在放置组件时是非常有效的。不过,天下没有免费的午餐,这同时也是最复杂的一种Layout,你需要自己写一个辅助的类来帮助你来管理某个GridBagConstraints的属性。可用性分析和GridBagLayou专家,James Tan,在4.3节中会带领我们全面的了解这个Layout。他还会给我们一个工具类来减轻我们处理GridBagConstaints属性时的繁重工作。

4.3 Using GridBagLayou

This section was written by James Tan, a systems analyst with United Overseas Bank Singapore(jtan@coruscant.per.sg)

在所有的SwingAWTLayout中,GridBagLayout是迄今(注:可能以后还会有更复杂的Layout,不过现在还是没有)最复杂的一种Layout。这一节中,我们将详细讲解GridBagLayout所依赖的GridBagConstraints,然后我们会列出一些代码来说明如何使用GridBagConstraints。我们后面将通过一个综合的input dialog,当然这个dialog使用到了所有的GridBagConstraints的属性,来深入讨论GridBagConstraints中的各个变量的使用。最后我们讲解一个我们自己设计的用来方便我们使用GridBagLayout的辅助类来结束我们GridBagLayout的学习。

4.3.1 Default behavior of GridBagLayout

简单的设置一个容器的LayoutGridBagLayout,然后把组件加到这个容器中,效果是这样的:

1、这些组件排成一行

2、每个组件都是自己的preferred size

3、这些组件仅仅的靠在一起(tightly packed)

4、所有的这些组件位于容器的中央

实际上默认情况下的GridBagConstraints是这样的

        gridx = RELATIVE;// 横向上,此组件位于上个组件的右边

        gridy = RELATIVE; // 纵向上,此组件上位于上个组件的右边

        gridwidth = 1;// 横向上,此组件跨越一个cell

        gridheight = 1; // 纵向上,此组件跨越一个cell

 

        weightx = 0;// 容器大小变化时,横向上,此组件cell不变

        weighty = 0; // 容器大小变化时,纵向上,此组件cell不变

        anchor = CENTER;// 组件位于cell的中央

        fill = NONE;// cell大小变化时,组件大小不会变

 

        insets = new Insets(0, 0, 0, 0);// 此组件的四周没有任何空间(如果和其他组件相邻时)

        ipadx = 0;// 横向上,此组件没有任何的附加大小

        ipady = 0; // 纵向上,此组件没有任何的附加大小

不像FlowLayoutGridBagLayout的容器的边界可以切割其内的组件,也就是说(当容器大小变化,导致一行放不下某个组件时)容器不会把其内的组件移动到下一行。下面的代码展示了这个特性。

见代码:

              /**

        * Default Behavior

        */

4.3.2 Introducing GridBagConstraints

如果一个容器被分配了GridBagLayoutLayout,那么当我们直接向这个容器添加组件时,Layout Manager会根据默认的GridBagConstraints对象来放置我们加上的组件。就像上面我的例子那样。通过自己创建一个GridBagConstraints对象,然后给这个对象设置属性值,然后把这个GridBagConstraits对象在add组件时也当作add()方法的参数,这样我们就可以非常有弹性的来控制我们组件的位置的放置。

下面列出的是我们可以设置GridBagConstraints的所有的属性,以及这些属性的默认值,这些属性的行为我们会在下面的例子中来一一阐述。

public int gridx = GridBagConstraints.RELATIVE;

public int gridy = GridBagConstraints.RELATIVE;

public int gridwidth = 1;

public int gridheight = 1;

public double weightx = 0.0;

public double weighty = 0.0;

public int anchor = GridBagConstraints.CENTER;

public int fill = GridBagConstraints.NONE;

public Insets insets = new Insets( 0, 0, 0, 0 );

public int ipadx = 0;

public int ipady = 0;

4.3.3 Using the gridx, gridy, ipadx, and ipady constraints

gridx, griy属性用来确切的指定,我们希望我们的组件在cell中所处的具体的位置。组件的初始放置位置从容器的左上角开始,gridx, gridy的初始值是0。如果给它们指定负值,那么就相当于指定它们为RELATIVE,这时的意思是:这个将要加上的组件位于上一个组件的后面(即位于上一个组件的右面或者下面)

insets属性会围绕着这个组件,在这个组件的外部加上个不可见的夹垫(padding),如果是负值,则意思是使得这个组件变得比起所在cell更大。

ipadx, ipady属性会给这个组件加上个内部夹垫(padding),这时此组件的preferred size的值会计算入这个内部夹垫。非常明确的是,ipadx属性会把此组件的preferred width的值加上ipadx*2,同样ipady属性会把此组件的preferred height的值加上ipady*2(*2是因为这个夹垫(padding)会在此组件的两边都加上)

在下面的例子中,我们把按钮”Wonderful” ”World”放到第一行,其他的两个按钮放到第二行。我们也给每个按钮都分配insets,这样这些按钮看起来就不会那么拥挤了。按钮的大小也是不一样(ipdax, ipady所改变的)

见代码:

              /**

        * gridx, ipadx, insets

        */

我们首先创建了一个GridBagConstraints对象,然后设置这个对象的各个属性,然后利用这个对象来把第一个按钮加给容器。然后我们还用这个对象,改变这个对象的相应的值,然后再利用这个对象把其他的组件加到容器内。这样节省了内存,而且我们也避免了在设置其他不需要修改的值。

4.3.4 Using the weightx and weighty constraints(如何给cell分配多余的空间,默认0,0)

在上面的例子中,当容器的大小改变时,容器内的组件遵循我们所设置的约束条件而变化(the components respect the constrains we have assigned),但是整个容器内的组件整体却始终都位于容器的中间。那么,问题来了:为什么我们的组件变化,从而按一定的比例来占据他们周围的空间呢?答案就在于weightx, weighty 属性,这两个属性当GridBagConstraints在初始化时都是0

这两个属性用来指定(当容器的大小变化时)如何把容器内的多余的空间分配到每个组件的cell中。属性weightx用来指定使用这个GridBagConstraints的组件如何占据水平的多余的空间。类似地,属性weighty用来指定使用这个GridBagConstraints的组件如何占据垂直的多余的空间。这两个约束被分配的值是0.0----1.0

举例来说,我们有两个按钮AB分别放在row 0column0column1。如果我为A指定了weightx=1.0,为B指定weightx=0,那么当我们改变容器的大小时,所有的空间将分配给按钮A的cell(注意:空间分给了cell,而不是cell内的组件)。(当然,这里,至于按钮A在这个cell内位于什么方位,以及空间比以前大了后,A又是如何变化的,那都取决于ancher, fill属性。)B按钮则被尽可能远的推倒了容器的右边。

回到我们的”Wonderful World Of Swing!!!”例子,我们修改我们的程序,使得当容器增大时,所有的按钮的cell都得到相等的多出来的空间(由于容器增大而多出来的空间)。指定weightx, weighty都是1.0。然后当加任何一个组件时都使用同样的约束,这样GridBayLayout就会把所有的可用的空间平均分配到每个cell上。

见程序

       /**

        * 3. weightx

        */

4.3.5 Using the gridwidth and gridheight constraints(使组件跨越多个cell,默认值:1,只占据一个cell)

GridBagLayout也允许我们让一个组件跨越多个cell,这时我们就用到了gridwidth, gridheight。为了展示这个示例,我们修改我们的程序,让我们的按钮”Wonderful”占用两个行,让我们的”World”按钮占用两个列。注意:如果占用了多个cell,那么就会基于当前的容器的大小而创建多个行或列,这样我们后面再设置gridx/gridy属性时则还要计算上此处的gridwidth或gridheight。

见程序:

              /**

        * gridwidth, occupy more column

        */

4.3.6 Using anchor constraints(默认值:GridBagConstraints.CENTER)

我们可以控制一个组件在它所属的cell(s)内是如何摆放(aligned)的,这时就用到了GridBagConstraintsanchor属性,默认的是GridBagConstraints.CENTER,所以默认情况下组件就被放置到了这个组件所占据的cell(s)的中间,关于anchor有下列的9种设置:

GridBagConstraints.NORTH

GridBagConstraints.SOUTH

GridBagConstraints.EAST

GridBagConstraints.WEST

GridBagConstraints.CENTER

GridBagConstraints.NORTHEAST

GridBagConstraints.NORTHWEST

GridBagConstraints.SOUTHEAST

GridBagConstraints.SOUTHWEST

下面的代码中,我们修改anchor属性,从而将”Wonderful”按钮放到它自己所在的cellNORTH”World”按钮放到它自己所在的cellSOUTHWEST”Of” ”Swing!!!”按钮放到他们自己的cellCENTER

见代码:

              /**

        * ancher in a cell

        */

4.3.7 Using fill constraints(默认值:GridBagConstraints.NONE)

要跨越多个组件的原因就是我们希望包含在某个cell(s)内的组件占据多余的这些cell的空间。要作到这个,我们可以像上面介绍的那样使用gridheight/gridwidth约束,以及我们将要介绍的fill约束。fill约束可以使用下面的四个值之一:

GridBagConstraints.NONE

GridBagConstraints.HORIZONTAL

GridBagConstraints.VERTICAL

GridBagConstraints.BOTH

注意:使用fill属性时,必须设置weightx, weighty皆>0否则,fill属性没有作用的。

在下面的代码中,我们修改代码,使得”Wonderful”按钮占据所有的(自己cell内的)可用的空间,包括横向和纵向;”World”按钮则占据(自己cell内的)所有的水平空间,而纵向上则还是用按钮自己的preferred vertical size”Of”按钮不使用fill约束,也就是说,使用默认值NONE,这样在横向和纵向上此按钮的大小都是preferred size”Swing!!!”按钮则使用(自己cell内的)所有的纵向空间,而横向上还是使用按钮自己的preferred horizontal size

见代码:

              /**

        * fill in a cell

        */

 

 


import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;

/**
 * This Demo is tidid up from a demo from Manning - Java Swing 2nd Edition (2005)
 * wish it is useful for you to learn GridBagLayout
 * 
@author Marvin
 *
 
*/

public class GridBagDemo extends JFrame {
    
public GridBagDemo() {
        
super("GridBagDemo");
        setSize(
800600);

        JDesktopPane desktop 
= new JDesktopPane();
        getContentPane().add(desktop);

        
/**
         * Default Behavior
         
*/

        JInternalFrame dft 
= new JInternalFrame("Default Behavior"truetrue);
        dft.setBounds(
55300140);
        Container contentPane 
= dft.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        contentPane.add(
new JButton("Wonderful"));
        contentPane.add(
new JButton("World"));
        contentPane.add(
new JButton("Of"));
        contentPane.add(
new JButton("Swing!!!"));
        desktop.add(dft, 
0);
        dft.show();

        
/**
         * gridx, ipadx, insets
         
*/

        JInternalFrame gridx_ipadx_insets 
= new JInternalFrame(
                
"gridx_ipadx_insets"truetrue);
        gridx_ipadx_insets.setBounds(
5150300140);
        contentPane 
= gridx_ipadx_insets.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        GridBagConstraints constrains 
= new GridBagConstraints();
        constrains.insets 
= new Insets(2222);
        constrains.gridx 
= 0;// column 0
        constrains.gridy = 0;// row 0
        constrains.ipadx = 5;// Increase component width by 10 pixels
        constrains.ipady = 5;// Increase component height by 10 pixels
        contentPane.add(new JButton("Wonderful"), constrains);

        constrains.gridx 
= 1;
        constrains.ipadx 
= 0;// Reset the padding to 0
        constrains.ipady = 0;// Increase component height by 10 pixels
        contentPane.add(new JButton("World"), constrains);

        constrains.gridx 
= 0;// column 0
        constrains.gridy = 1;// row 1
        contentPane.add(new JButton("Of"), constrains);

        constrains.gridx 
= 1;// column 1
        contentPane.add(new JButton("Swing!!!"), constrains);

        desktop.add(gridx_ipadx_insets, 
1);
        gridx_ipadx_insets.show();

        
/**
         * weightx
         
*/

        JInternalFrame weightx_weighty 
= new JInternalFrame("weightx"true,
                
true);
        weightx_weighty.setBounds(
5295300140);
        contentPane 
= weightx_weighty.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        constrains 
= new GridBagConstraints();
        constrains.insets 
= new Insets(2222);
        constrains.weightx 
= 1.0;
        constrains.weighty 
= 1.0;
        constrains.gridx 
= 0;// column 0
        constrains.gridy = 0;// row 0
        contentPane.add(new JButton("Wonderful"), constrains);

        constrains.gridx 
= 1;// column 1
        contentPane.add(new JButton("World"), constrains);

        constrains.gridx 
= 0;// column 0
        constrains.gridy = 1;// row 1

        contentPane.add(
new JButton("Of"), constrains);

        constrains.gridx 
= 1;// column 1
        contentPane.add(new JButton("Swing!!!"), constrains);
        desktop.add(weightx_weighty, 
2);
        weightx_weighty.show();

        
/**
         * gridwidth, occupy more column
         
*/

        JInternalFrame gridwidth_occupyMoreColumn 
= new JInternalFrame(
                
"gridwidth_occupyMoreColumn"truetrue);
        gridwidth_occupyMoreColumn.setBounds(
3505300140);
        contentPane 
= gridwidth_occupyMoreColumn.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        constrains 
= new GridBagConstraints();

        constrains.insets 
= new Insets(2222);
        constrains.gridx 
= 0;
        constrains.gridy 
= 0;
        constrains.weightx 
= 1.0;
        constrains.weighty 
= 1.0;
        constrains.gridheight 
= 2;// Span accross 2 row
        contentPane.add(new JButton("Wonderful"), constrains);

        constrains.gridx 
= 1;
        constrains.gridheight 
= 1;// Remember to set back to 1 row
        constrains.gridwidth = 2;// Span accross 2 column
        contentPane.add(new JButton("World"), constrains);

        constrains.gridy 
= 1;
        constrains.gridwidth 
= 1;// Remember to set back to 1 column
        contentPane.add(new JButton("Of"), constrains);

        constrains.gridx 
= 2;
        contentPane.add(
new JButton("Swing!!!"), constrains);
        desktop.add(gridwidth_occupyMoreColumn, 
3);
        gridwidth_occupyMoreColumn.show();

        
/**
         * ancher in a cell
         
*/

        JInternalFrame ancher_in_cell_position 
= new JInternalFrame(
                
"ancher_in_cell_position"truetrue);
        ancher_in_cell_position.setBounds(
350150300140);
        contentPane 
= ancher_in_cell_position.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        constrains 
= new GridBagConstraints();
        constrains.insets 
= new Insets(2222);
        constrains.weightx 
= 1.0;
        constrains.weighty 
= 1.0;
        constrains.gridx 
= 0;
        constrains.gridy 
= 0;
        constrains.gridheight 
= 2;
        constrains.anchor 
= GridBagConstraints.NORTH;
        contentPane.add(
new JButton("Wonderful"), constrains);

        constrains.gridx 
= 1;
        constrains.gridheight 
= 1;
        constrains.gridwidth 
= 2;
        constrains.anchor 
= GridBagConstraints.SOUTHWEST;
        contentPane.add(
new JButton("World"), constrains);

        constrains.gridy 
= 1;
        constrains.gridwidth 
= 1;
        constrains.anchor 
= GridBagConstraints.CENTER;
        contentPane.add(
new JButton("Of"), constrains);

        constrains.gridx 
= 2;
        contentPane.add(
new JButton("Swing!!!"), constrains);
        desktop.add(ancher_in_cell_position, 
4);
        ancher_in_cell_position.show();

        
/**
         * fill in a cell
         
*/

        JInternalFrame fill_the_cell 
= new JInternalFrame("fill_the_cell",
                
truetrue);
        fill_the_cell.setBounds(
350295300140);
        contentPane 
= fill_the_cell.getContentPane();
        contentPane.setLayout(
new GridBagLayout());
        constrains 
= new GridBagConstraints();
        constrains.insets 
= new Insets(2222);
        constrains.weightx 
= 1.0;
        constrains.weighty 
= 1.0;
        constrains.gridx 
= 0;
        constrains.gridy 
= 0;
        constrains.gridheight 
= 2;
        constrains.fill 
= GridBagConstraints.BOTH;
        contentPane.add(
new JButton("Wonderful"), constrains);

        constrains.gridx 
= 1;
        constrains.gridheight 
= 1;
        constrains.gridwidth 
= 2;
        constrains.fill 
= GridBagConstraints.HORIZONTAL;
        contentPane.add(
new JButton("World"), constrains);

        constrains.gridy 
= 1;
        constrains.gridwidth 
= 1;
        constrains.fill 
= GridBagConstraints.NONE;
        contentPane.add(
new JButton("Of"), constrains);

        constrains.gridx 
= 2;
        constrains.fill 
= GridBagConstraints.VERTICAL;
        contentPane.add(
new JButton("Swing!!!"), constrains);
        desktop.add(fill_the_cell, 
5);
        fill_the_cell.show();
        WindowListener wndCloser 
= new WindowAdapter() {
            
public void windowClosing(WindowEvent e) {
                System.exit(
0);
            }

        }
;
        addWindowListener(wndCloser);
        setVisible(
true);
    }


    
public static void main(String argv[]) {
        
new GridBagDemo();
    }

}

 

 

原创粉丝点击