深入学习GridBagLayout

转自 http://www.cnblogs.com/renyuan/archive/2012/10/15/2723809.html

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

对于简单的程序使用Boborderlayout和Gridlayout就绰绰有余了, 但如果要把程序提到实际应用上你就得考虑使用GridBagLayout。当然, 做复杂的应用程序时,一开始就使用GridBagLayout就会更有效率。一旦你决定使用GridBagLayout,接下来一步便是要找一些纸和铅笔,只有你准确知道你的界面看上去需要成什么样子,你就可以敲键盘。这就是说,你应该在编码之前进行妥善规划。

昨天看了一晚上Swing 联想到做前端的经历, 我对能够自由操作组件的依赖性很高, 否则会让我觉得很别扭. 脑海里重复对比思考六种布局管理器. 最终将最终的选择放在了网络包管理器, 我不觉得它很复杂,倒是觉得正是这些灵活性使得 我拥有更多的自由操纵组件的空间.

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

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

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章