Swing布局

前言

swing是Java中的一个gui库。现在已经很少看到有使用swing开发的项目了.我也一直没有真正的使用swing进行开发,只是在刚接触java时根据例子简单敲了一下。不过最近,公司正好有一个项目是以swing为基础进行二次开发的,作为一个几乎近似于刚接触swing的新手,在接下来的日子里简单记录一下学习swing的一些内容。以下,为swing中的关键,layout方面的内容。

BorderLayout

一种非常简单常用的布局策略, 也是某些容器组件的默认布局管理器,即RootPaneContainer(JInternalFrame、JDialog、JFrame、JWindow),它将容器分为NORTH, SOUTH,CENTER,WEST,EAST五个区域, 每个区域最多只能有一个组件. East和West的组件在垂直方向上拉升,North和South的组件在水平方向上拉升,Center的组件可同时在水平和垂直方向上拉升,填满所有剩余空间.

使用方式:

1
Container.add(component, BorderLayout.EAST);

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	JFrame testFrame = new JFrame();
testFrame.setSize(600, 600);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
testFrame.setContentPane(contentPane);
JButton button1 = new JButton("北");
JButton button2 = new JButton("南");
JButton button3 = new JButton("东");
JButton button4 = new JButton("西");
JButton button5 = new JButton("中央");
testFrame.setLayout(new BorderLayout());
contentPane.add(button1, "North");
contentPane.add(button2, "South");
contentPane.add(button3, "East");
contentPane.add(button4, "West");
contentPane.add(button5, "Center");
testFrame.setVisible(true);

// 具体可通过鼠标拖动窗体伸缩查看效果

显示:

若不指定第二个参数,则默认在BorderLayout.CENTER区域显示
如果对同一个区域添加了多个组件,那么只显示最后添加的组件。

FlowLayout

该布局是从左到右或从右到左方式排列,一行放不下就换到另外一行。因此它一行能放置多少组件取决于窗口的宽度。如果剩余空间小于组件,那么组件将在新行显示。注意它默认组件是居中对齐,可以通过FlowLayout(intalign)函数来指定对齐方式。是JPanel的默认的布局管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.awt.FlowLayout;

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

public class Test01 {

public static void main(String[] args) {
JFrame testFrame = new JFrame();
testFrame.setSize(600, 600);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
testFrame.setContentPane(panel);
FlowLayout layout = new FlowLayout();
testFrame.setLayout(layout);
JButton button1 = new JButton("button1");
JButton button2 = new JButton("button2");
JButton button3 = new JButton("button3");
JButton button4 = new JButton("button4");
JButton button5 = new JButton("button5");
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
testFrame.setVisible(true);
}
}

// 具体可通过鼠标拖动窗体伸缩查看效果

注:
// 设置组件之间的距离
setVgap(int vgap) 设置组件之间以及组件与 Container 的边之间的垂直间隙。

setHgap(int hgap) 设置组件之间以及组件与 Container 的边之间的水平间隙。

GridLayout

网格式的布局,将整个容器划分成一定的行和一定的列,可以指定控件放在某行某列上,窗口改变的时候,组件的大小也会随之改变。每个单元格的大小一样,而且放置组件时,只能从左到右、由上到下的顺序填充,用户不能任意放置组件,比较的“死板”。

简单一点来说, GridLayout就类似于一个标准的表格,但是最麻烦的是,这种布局不能跨行和跨列,所以感觉应该很少能用到这个布局方式。虽然可以在子组件中设置不同的布局方式进行搭配,使展示效果达到跨行跨列的效果,但是这已经与GridLayout没什么关系了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
GridLayout有三个构造方法

GridLayout() // 创建具有默认值的网格布局,即每个组件占据一行一列。
GridLayout(int rows, int cols) // 创建具有指定行数和列数的网格布局。
GridLayout(int rows, int cols, int hgap, int vgap) // 创建具有指定行数和列数的网格布局。

// 以GridLayout(int rows, int cols)为例:

public static void main(String[] args) {
JFrame testFrame = new JFrame();
testFrame.setSize(600, 600);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
testFrame.setContentPane(panel);
GridLayout layout = new GridLayout(3,2);
testFrame.setLayout(layout);
JButton button1 = new JButton("button1");
JButton button2 = new JButton("button2");
JButton button3 = new JButton("button3");
JButton button4 = new JButton("button4");
JButton button5 = new JButton("button5");
JButton button6 = new JButton("button6");
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);
testFrame.setVisible(true);
}

显示:

GridBagLayout

上面说GridLayout无法跨行和跨列,那么使用GridBagLayout就可以达到跨行跨列的效果,我想,在正式环境中应该使用GridBagLayout的情况反而更多。

GridBagLayout比较复杂,需要通过GridBagConstraints类进行约束。

GridBagConstraints常用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fill :指定填充方向,可以向水平,垂直或水平+垂直方向充满整个容器
gridx(), gridy() 指定组件在容器单元格内的行索引与列索引,如最左上的那个单元格式,其gridx为0,gridy为0
gridwidth(), gridheight() :指定单元格的跨行与跨列数
insets :指定组件的外部填充,相当于单元格间距
weightx, weighty :指定容器大小变动时,向x或y方向的伸缩率。
Anchor:当组件的大小小于可用显示区域时使用,指定组件在显示区域中的位置。 请见下图:

-------------------------------------------------
|FIRST_LINE_START PAGE_START FIRST_LINE_END|
| |
| |
|LINE_START CENTER LINE_END|
| |
| |
|LAST_LINE_START PAGE_END LAST_LINE_END|
-------------------------------------------------

以下给出一个GridBagLayout的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.awt.Button;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;

public class GridBagLayoutTest {

// 新建了一块场地
private JFrame f = new JFrame("小区");
// 聘请了一位资深的园艺设计师
private GridBagLayout gb = new GridBagLayout();
// 要设计,就要有一张空白的设计图纸
private GridBagConstraints gbc = new GridBagConstraints();
// 订购了十棵树
private Button[] bs = new Button[11];

public void init() {
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setSize(1000, 1000);
// 指定设计师要设计的地盘
f.setLayout(gb);
// 把十棵树先准备好
for (int i = 0; i < bs.length; i++) {
bs[i] = new Button("树" + i);
}
// 启用组件横向、纵向上扩展的功能
gbc.fill = GridBagConstraints.BOTH;

// 设置组件横向上扩展的比例,在一行上有多个组件时有用
gbc.weightx = 1;

// 中第一棵树
addButton(bs[0]);
// 中第二棵树
addButton(bs[1]);
addButton(bs[2]);

// 中的第四棵树是这一行的最后一棵树
gbc.gridwidth = GridBagConstraints.REMAINDER;
addButton(bs[3]);

// 中的第五课树会从第二行开始,这棵树也是该行最后一棵树,增加纵向长度
gbc.ipady = 20;
addButton(bs[4]);

// 从第三行开始种,横向占了两棵树的位置
gbc.ipady = 0;
gbc.gridwidth = 2;
addButton(bs[5]);

// 第三行的最后一棵树,自然横向占两棵树的位置
gbc.gridwidth = GridBagConstraints.REMAINDER;
addButton(bs[6]);

// 第四行第一棵树恢复横向占一棵树的位置
gbc.gridwidth = 1;
// 纵向跨越两个网格
gbc.gridheight = 2;
addButton(bs[7]);

// 种第四行最后一棵树,自然横向跨越三棵树的位置
gbc.gridwidth = GridBagConstraints.REMAINDER;
// 恢复纵向跨越一个网格
gbc.gridheight = 1;
addButton(bs[8]);
// 接在第八棵树后面,但在第九棵树的下一行,真正实现了让第八棵树纵跨两行
addButton(bs[9]);
// 第十一课树会出现在第五行,因为没有给gridwidth重新赋值,它就是第五行最后一棵树
// 将其设为纵向扩展,由于第十一棵树要纵向扩展,它会在上下两个方向不断膨胀,结果把它上面的组件都挤到
// 最上面去了
gbc.weighty = 1;
addButton(bs[10]);
// 使得场地的大小刚好容得下目前已种的树
// f.pack();
// 把设计好的场地展现出来
f.setVisible(true);
}

// 将当前的树如何植入小区,植入小区哪边的方法
private void addButton(Button button) {
// 先要确保设计师手上有设计图纸和材料
gb.setConstraints(button, gbc);
// 将树植入
f.add(button);
}

public static void main(String[] args) {
new GridBagLayoutTest().init();
}
}

// 以上这个例子是我在网上找资料的时候在一个论坛上看到的,感觉可以很好说明GridBagLayout.具体链接地址在哪里忘记了,惭愧。不过感谢那位仁兄对我的帮助

CardLayout

CardLayout 对象是容器的布局管理器。它将容器中的每个组件看作一张卡片。一次只能看到一张卡片,容器则充当卡片的堆栈。当容器第一次显示时,第一个添加到 CardLayout 对象的组件为可见组件

CardLayout的布局感觉有点像之前我记单词时用的单词卡一样,还有在有些APP中点击切切换页面可能也会使用到CardLayout. 其实个人感觉来说,这个布局就像是常用的Tab页,如JTabbedPane,去除头部标题那一部分的效果

GroupLayout

GroupLayout是一个非常复杂的Layout,此布局有一个轴的概念. 水平轴与垂直抽. 这个布局我很少接触,贴一些引用,待需要用到时再查找

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public static void main(String[] args) {
JFrame jf = new JFrame("测试窗口");
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

// 创建内容面板容器
JPanel panel = new JPanel();
// 创建分组布局,并关联容器
GroupLayout layout = new GroupLayout(panel);
// 设置容器的布局
panel.setLayout(layout);

// 创建组件
JButton btn01 = new JButton("Button01");
JButton btn02 = new JButton("Button02");
JButton btn03 = new JButton("Button03");
JButton btn04 = new JButton("Button04");
JButton btn05 = new JButton("Button05");

// 自动创建组件之间的间隙
layout.setAutoCreateGaps(true);
// 自动创建容器与触到容器边框的组件之间的间隙
layout.setAutoCreateContainerGaps(true);

/*
* 水平组(仅确定 X 轴方向的坐标/排列方式)
*
* 水平串行: 水平排列(左右排列)
* 水平并行: 垂直排列(上下排列)
*/
// 水平并行(上下) btn01 和 btn02
GroupLayout.ParallelGroup hParalGroup01 = layout.createParallelGroup().addComponent(btn01).addComponent(btn02);

// 水平并行(上下)btn03 和 btn04
GroupLayout.ParallelGroup hParalGroup02 = layout.createParallelGroup().addComponent(btn03).addComponent(btn04);

// 水平串行(左右)hParalGroup01 和 hParalGroup02
GroupLayout.SequentialGroup hSeqGroup = layout.createSequentialGroup().addGroup(hParalGroup01).addGroup(hParalGroup02);

// 水平并行(上下)hSeqGroup 和 btn05
GroupLayout.ParallelGroup hParalGroup = layout.createParallelGroup().addGroup(hSeqGroup).addComponent(btn05, GroupLayout.Alignment.CENTER);

layout.setHorizontalGroup(hParalGroup); // 指定布局的 水平组(水平坐标)

/*
* 垂直组(仅确定 Y 轴方向的坐标/排列方式)
*
* 垂直串行: 垂直排列(上下排列)
* 垂直并行: 水平排列(左右排列)
*/
// 垂直并行(左右)btn01 和 btn03
GroupLayout.ParallelGroup vParalGroup01 = layout.createParallelGroup().addComponent(btn01).addComponent(btn03);

// 垂直并行(左右)btn02 和 btn04
GroupLayout.ParallelGroup vParalGroup02 = layout.createParallelGroup().addComponent(btn02).addComponent(btn04);

// 垂直串行(上下)vParalGroup01, vParalGroup02 和 btn05
GroupLayout.SequentialGroup vSeqGroup = layout.createSequentialGroup().addGroup(vParalGroup01).addGroup(vParalGroup02).addComponent(btn05);

layout.setVerticalGroup(vSeqGroup); // 指定布局的 垂直组(垂直坐标)

jf.setContentPane(panel);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}

BoxLayout

BoxLayout也是一个比较强大的布局管理器, 它既可以设置横向排列页可以设置纵向排列。

主要排列方式包括

1
2
3
4
5
6
7
X_AXIS:从左到右水平布置组件。

Y_AXIS:从上到下垂直布置组件。

LINE_AXIS:根据容器的ComponentOrientation属性,按照行的方式排列,可以从左到右也可以从右到左

PAGE_AXIS:根据容器的ComponentOrientation,以页面的方式进行排列

关于BoxLayout通常与Box容器进行搭配使用,Box可以创建一些影响布局的组件提高显示效果。glue、struts 和 rigid 区域。 比如有时候我们希望不同的组件之间留一些间隔,空白区域,我们就可以在不同的组件之间利用Box创建一些隐藏不可见的组件。

Box类常用方法:

1
2
3
4
5
6
7
createHorizontalBox() // 创建一个从左到右显示其组件的 Box。

createVerticalBox() // 创建一个从上到下显示其组件的 Box。

createHorizontalGlue() // 创建一个横向 glue 组件。

createVerticalGlue() // 创建一个纵向 glue 组件。

关于Boxlayout在网上看到很多写的很好的博客,这里抛砖引入,使用其中一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package boxlayout.test;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;

public class BoxLayoutTest {

static JPanel topPanel;
static JPanel bottomPanel;
static JPanel middlePanel;

static void createTopPanel() {
topPanel = new JPanel();
String[] columnName = { "姓名", "性别", "单位", "参加项目", "备注" };
String[][] rowData = { { "张三", "男", "计算机系", "100 米 ,200 米", "" }, { "李四", "男", "化学系", "100 米,铅球", "" }, };
// 创建表格
JTable table = new JTable(new DefaultTableModel(rowData, columnName));
// 创建包含表格的滚动窗格
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// 定义 topPanel 的布局为 BoxLayout,BoxLayout 为垂直排列
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
// 先加入一个不可见的 Strut,从而使 topPanel 对顶部留出一定的空间
topPanel.add(Box.createVerticalStrut(10));
// 加入包含表格的滚动窗格
topPanel.add(scrollPane);
// 再加入一个不可见的 Strut,从而使 topPanel 和 middlePanel 之间留出一定的空间
topPanel.add(Box.createVerticalStrut(10));
}

@SuppressWarnings({ "rawtypes", "unchecked" })
static void createMiddlePanel() {
// 创建 middlePanel
middlePanel = new JPanel();
// 采用水平布局
middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.X_AXIS));
// 创建标签运动会项目
JLabel sourceLabel = new JLabel("运动会项目:");
sourceLabel.setAlignmentY(Component.TOP_ALIGNMENT);
sourceLabel.setBorder(BorderFactory.createEmptyBorder(4, 5, 0, 5));
// 创建列表运动会项目
DefaultListModel listModel = new DefaultListModel();
listModel.addElement("100 米");
listModel.addElement("200 米");
listModel.addElement("400 米");
listModel.addElement("跳远");
listModel.addElement("跳高");
listModel.addElement("铅球");
JList sourceList = new JList(listModel);
sourceList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
sourceList.setVisibleRowCount(5);
JScrollPane sourceListScroller = new JScrollPane(sourceList);
sourceListScroller.setPreferredSize(new Dimension(120, 80));
sourceListScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
sourceListScroller.setAlignmentY(Component.TOP_ALIGNMENT);
// 创建最左边的 Panel
JPanel sourceListPanel = new JPanel();
// 最左边的 Panel 采用水平布局
sourceListPanel.setLayout(new BoxLayout(sourceListPanel, BoxLayout.X_AXIS));
// 加入标签到最左边的 Panel
sourceListPanel.add(sourceLabel);
// 加入列表运动会项目到最左边的 Panel
sourceListPanel.add(sourceListScroller);
sourceListPanel.setAlignmentY(Component.TOP_ALIGNMENT);
sourceListPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 30));
// 将最左边的 Panel 加入到 middlePanel
middlePanel.add(sourceListPanel);
// 定义中间的两个按钮
JButton toTargetButton = new JButton(">>");
JButton toSourceButton = new JButton("<<");
// 定义中间的 Panel
JPanel buttonPanel = new JPanel();
// 中间的 Panel 采用水平布局
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
// 将按钮 >> 加入到中间的 Panel
buttonPanel.add(toTargetButton);

// 两个按钮之间加入一个不可见的 rigidArea
buttonPanel.add(Box.createRigidArea(new Dimension(15, 15)));
// 将按钮 << 加入到中间的 Panel
buttonPanel.add(toSourceButton);
buttonPanel.setAlignmentY(Component.TOP_ALIGNMENT);
buttonPanel.setBorder(BorderFactory.createEmptyBorder(15, 5, 15, 5));
// 将中间的 Panel 加入到 middlePanel
middlePanel.add(buttonPanel);
// 创建标签查询项目
JLabel targetLabel = new JLabel("查询项目:");
targetLabel.setAlignmentY(Component.TOP_ALIGNMENT);
targetLabel.setBorder(BorderFactory.createEmptyBorder(4, 5, 0, 5));

// 创建列表查询项目
DefaultListModel targetListModel = new DefaultListModel();
targetListModel.addElement("100 米");
JList targetList = new JList(targetListModel);
targetList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
targetList.setVisibleRowCount(5);
JScrollPane targetListScroller = new JScrollPane(targetList);
targetListScroller.setPreferredSize(new Dimension(120, 80));
targetListScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
targetListScroller.setAlignmentY(Component.TOP_ALIGNMENT);
// 创建最右边的 Panel
JPanel targetListPanel = new JPanel();
// 设置最右边的 Panel 为水平布局
targetListPanel.setLayout(new BoxLayout(targetListPanel, BoxLayout.X_AXIS));
// 将标签查询项目加到最右边的 Panel
targetListPanel.add(targetLabel);
// 将列表查询项目加到最右边的 Panel
targetListPanel.add(targetListScroller);
targetListPanel.setAlignmentY(Component.TOP_ALIGNMENT);
targetListPanel.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0));
// 最后将最右边的 Panel 加入到 middlePanel
middlePanel.add(targetListPanel);
}

static void createBottomPanel() {
// 创建查询按钮
JButton actionButton = new JButton("查询");
// 创建退出按钮
JButton closeButton = new JButton("退出");
// 创建 bottomPanel
bottomPanel = new JPanel();
// 设置 bottomPanel 为垂直布局
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
// 创建包含两个按钮的 buttonPanel
JPanel buttonPanel = new JPanel();
// 设置 bottomPanel 为水平布局
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
// 将查询按钮加入到 buttonPanel
buttonPanel.add(actionButton);

// 加入一个 glue, glue 会挤占两个按钮之间的空间
buttonPanel.add(Box.createHorizontalGlue());
// 将退出按钮加入到 buttonPanel
buttonPanel.add(closeButton);
// 加入一个 Strut,从而使 bottomPanel 和 middlePanel 上下之间留出距离
bottomPanel.add(Box.createVerticalStrut(10));
// 加入 buttonPanel
bottomPanel.add(buttonPanel);
// 加入一个 Strut,从而使 bottomPanel 和底部之间留出距离
bottomPanel.add(Box.createVerticalStrut(10));
}

public static void main(String[] args) {
// 创建 topPanel
createTopPanel();
// 创建 middlePanel
createMiddlePanel();
// 创建 bottomPanel
createBottomPanel();
// 创建包含 topPanel,middlePanel 和 bottomPanel 的 panelContainer
JPanel panelContainer = new JPanel();
// panelContainer 的布局为 GridBagLayout
panelContainer.setLayout(new GridBagLayout());

GridBagConstraints c1 = new GridBagConstraints();
c1.gridx = 0;
c1.gridy = 0;
c1.weightx = 1.0;
c1.weighty = 1.0;
c1.fill = GridBagConstraints.BOTH;
// 加入 topPanel
panelContainer.add(topPanel, c1);

GridBagConstraints c2 = new GridBagConstraints();
c2.gridx = 0;
c2.gridy = 1;
c2.weightx = 1.0;
c2.weighty = 0;
c2.fill = GridBagConstraints.HORIZONTAL;
// 加入 middlePanel
panelContainer.add(middlePanel, c2);

GridBagConstraints c3 = new GridBagConstraints();
c3.gridx = 0;
c3.gridy = 2;
c3.weightx = 1.0;
c3.weighty = 0;
c3.fill = GridBagConstraints.HORIZONTAL;
// 加入 bottomPanel
panelContainer.add(bottomPanel, c3);

// 创建窗体
JFrame frame = new JFrame("Boxlayout 演示");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panelContainer.setOpaque(true);
frame.setSize(new Dimension(480, 320));
frame.setContentPane(panelContainer);
frame.setVisible(true);
}
}

参考:

运用 BoxLayout 进行 Swing 控件布局

Swing框式布局(BoxLayout,Box)应用详解

TableLayout

TableLayout不是JDK自带的布局管理器,使用TableLayout需要首先引入它的jar包, 如果是maven项目,可以在maven中央仓库找到这个jar包

TabLayout API

TableLayout官方使用说明

如果有需要还是去官方文档去查看好了,里面有很多小demo可供参考。

对于官方文档中,行和列的大小设置,在此添加一点说明。 Tablelayout设定行和列,需要先定义一个二维数组,举例如下:

1
2
3
double size [] [] =
{{100, 0.50,0.20,TableLayout.FILL,200,TableLayout.FILL},
{TableLayout.FILL};

其中size[0]设置的时列的宽度,size[1]设置的时列的高度。在宽度中有几个概念需要说明:

名称 含义
总宽度 顾名思义,即容器的总宽度
绝对宽度 分配绝对像素大小的所有列的宽度成为绝对宽度
可缩放宽度 可缩放宽度=总宽度-绝对宽度
绝对列 使用绝对宽度指定的列是绝对列
可伸缩列 使用百分比指定的列称为可伸缩列
填充列 使用TableLayout.FILL指定
首选列 使用TableLayout.PREFERRED指定

关于宽度的分配原则为:

先将总宽度分配给绝对列和首选列,然后将剩余宽度(可伸缩宽度)分配给可伸缩列,如果可伸缩列的总和小于100%,则会留下一些可扩展的宽度。然后,在所有填充列中均等地划分该可缩放宽度

还是照着上面的例子来看,上面使用了一个二维数组size[][]来定义当前容器的列。

  • 第0列: 100px (绝对宽度)
  • 第1列: (500-100-200)*0.5 = 100px;
  • 第2列: (500-100-200)*0.2 = 40px;
  • 第3列: (500-100-200)*0.3/2 = 30px;
  • 第4列: 200px(绝对宽度)
  • 第5列: 同3列 30px;

关于这个宽度计算,我之前看文档的时候被绕了一段事件才搞明白。写在这里以作参考

总结

关于swing的布局策略,我的看法是,没有最好的layout,只有最适合当前业务场景的。能对不同的情况灵活选择,才是最好的。以上对一些常用的布局管理器进行了一些小小的总结,很多都是在网上查找资料是遇到的,我算是抛砖引玉了。当然,还有一些布局管理器没有说到,如:GridLayout,SpringLayout.等以后需要用到了再来查看吧。

另外留下SpringLayout的一些资源已备参考:

SpringLayout 管理器

How to use SpringLayout

SpringLayout API

参考:

Java-Swing常用布局管理器

官方使用文档