GridBagLayout使用

众所周知,GridBagLayout是swing提供的一种十分灵活的布局方式,正因其灵活性,所以每次用java做GUI程序时,我都会首选这种布局方式,但是每次用,感觉像扔色子猜点数,归其原因,主要是未理解GridBagLayout的设计理念,自然对其众多参数对布局的影响理解模棱两可,在做时只好去猜测各个参数含义,不断的尝试。这次做自己的一个小的java程序,在反复尝试下,终于明白了GridBagLayout的设计理念,如有错误之处,请多多指教。

概述

个人认为GridBagLayout设计理念是将父容器看作一个表格,表格中单元格的长宽可根据需求调整,可调整是指如下图1所示,通过竖线和横线的位置,来调整单元格大小,而不是如图2所示那样,任意的设置单元格大小,组件可以放在一个或多个连续的单元格中,且这些连续单元格最后所构成的区域必须是一个方形区域,下面我会以方格来代指这个方形区域。

示意图

据我所知,GridBagLayout不能够指定行数和列数,行数和列数是由swing根据父容器中各个组件设置的相关参数,自动计算出来的。如果读者发现可以明确指定行数和列数,请指教。

GridBagLayout参数

一个组件在父容器中的位置,由其设置的GridBagLayout的参数决定,而GridBagLayout参数封装在GridBagConstraints类中,其主要成员变量如下:

与组件所在方格相关的参数

变量名 作用
gridx 方格左上角单元格所在行号,行号在表格中以0开始,从左到右依次编号
gridy 方格左上角单元格所在列号,列号在表格中以0开始,从上到下依次编号
gridwidth 方格在横向占用的单元格数
gridheight 方格在纵向占用的单元格数
weightx 方格的长与表格长(即父容器的长)的比例,若为0,则为组件默认长度
weighty 方格的宽与表格宽(即父容器的宽)的比例,若为0,则为组件默认宽度

如下图所示,父容器被分割成3*3的表格,各行各列占比如图中小数所示,然后在该容器中分别放了方格1,方格2,方格3,以方格3为例,其gridx=0,gridy=2,gridwidth=2,gridheight=1,weightx=0.2,weighty=0.5。

示意图

效果图

代码如下:

package test.swing;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridWeightTest {
    
    public static void main(String[] args) {
        JFrame frame = new JFrame("GridWeightTest");
        frame.setLocation(10, 10);
        frame.setSize(600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        JPanel centerPane = new JPanel();
        
        frame.add(centerPane, BorderLayout.CENTER);
        
        centerPane.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        
        JButton btn1 = new JButton("方格1");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.gridheight = 2;
        gbc.weightx = 0.5;
        gbc.weighty = 0.8;
        centerPane.add(btn1, gbc);
        
        JButton btn2 = new JButton("方格2");
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.gridheight = 3;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        centerPane.add(btn2, gbc);
        
        JButton btn3 = new JButton("方格3");
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.gridheight = 1;
        gbc.weightx = 0.5;
        gbc.weighty = 0.2;
        centerPane.add(btn3, gbc);
        
        frame.setVisible(true);
    }
}

注:对于上面的参数个人理解不是十分充分,对于下图这种情况,方格1与方格3没有一条边是水平对齐的,我还没找出相应的参数设置方案,读者若有相应的参数设置方案,请指教。此外,读者若感兴趣,可以写代码测试下若行或者列上的所有weightx或weighty和不为1,swing会如何显示?

示意图

组件放置在方格中,即组件只能在其所在方格中显示,若组件比所在方格大,则只会显示组件的一部分,下面是与组件在方格中的位置,组件大小相关的参数:

变量名 作用
fill 但当组件比方格小时,组件如何填充方格中剩余空间,有水平填充(HORIZONTAL),垂直填充(VERTICAL)等方式,详细请看GridBagConstraints API
anchor 当组件比方格小时,组件在方格中的位置,可以是方格北方(WEST),方格南方(SOUTH),东方(EAST)等位置,详细请看GridBagConstraints API
JComponent.setPreferredSize 设置组件对象的大小,继承自JComponent的组件均可使用该方法,之所以在这儿加一个与GridBagLayout不相关的方法,是因为有时组件对象的默认大小不合适,而使用fill填充,也感觉不合适,那就只好由自己设置组件大小了

以实现下图效果为例。

示意图

效果图

代码如下:

package test.swing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class FillTest {
    
    public static void main(String[] args) {
        JFrame frame = new JFrame("FillTest");
        frame.setLocation(10, 10);
        frame.setSize(600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        JPanel centerPane = new JPanel();
        
        frame.add(centerPane, BorderLayout.CENTER);
        
        centerPane.setLayout(new GridBagLayout());
        centerPane.setBackground(Color.CYAN);
        GridBagConstraints gbc = new GridBagConstraints();
        
        JButton btn1 = new JButton("组件");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.gridheight = 2;
        gbc.weightx = 0.5;
        gbc.weighty = 0.8;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        centerPane.add(btn1, gbc);
        
        JButton btn2 = new JButton("组件");
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.gridheight = 3;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.CENTER;
        centerPane.add(btn2, gbc);
        
        JButton btn3 = new JButton("组件");
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.gridheight = 1;
        gbc.weightx = 0.5;
        gbc.weighty = 0.2;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.SOUTH;
        centerPane.add(btn3, gbc);
        
        frame.setVisible(true);
    }
}

其他参数

下面两个参数比较好理解,读者若感兴趣,不妨自己写代码测试,了解其作用。

变量名 作用
ipadx 自行测试
ipady 自行测试
insets 自行测试

swing零散技巧

  • 在父容器中添加许多组件后,如何让父容器出现滚动条?如何设置滚动条滚动速度?

JScrollPane sPane = new JScrollPane(centerPanel),设置滚动条垂直(竖向类似)速度sPane.getVerticalScrollBar().setUnitIncrement(要设置的速度);

  • 删除父容器中的组件后,但是父容器没有变化,如何可以立即刷新父容器?

不妨试着调用父容器或者父容器的validate()或者doLayout()或者repaint()方法



作者:墙角的蝈蝈
链接:https://www.jianshu.com/p/b0f781c3e8c2
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

猜你喜欢

转载自blog.csdn.net/u010499087/article/details/98964765
今日推荐