众所周知,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
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。