12.3 Swing中的特殊容器 12.3.1 使用JsplitPane 分割面板

12.3 Swing中的特殊容器

Swing提供了一些具有特殊功能的容器,这些特殊容器可以用于创建一些更复杂的用户界面。下面将依次介绍这些特殊容器。

12.3.1 使用JsplitPane 分割面板

JSplitPane用于创建一个分割面板,它可以将一个组件(通常是一个容器)分割成两个部分,并提供一个分割条,用户可以拖动该分割条来调整两个部分的大小。图12.13显示了分割面板效果,图中所示的窗口先被分成左右两块,其中左边一块又被分为上下两块
这里有一张图片

如何创建分割面板

从图12.13中可以看岀,分割面板的实质是一个特殊容器,该容器只能容纳两个组件,而且分割面板又分为上下分割、左右分割两种情形,所以创建分割面板的代码非常简单,如下代码所示。

1
new JSplitPane(方向,左/上组件,右/下组件);

除此之外,创建分割面板时可以指定一个newContinuousLayout参数,该参数指定该分割面板是否支持“连续布局”。
如果分割面板支持连续布局,则用户拖动分割条时两边组件将会不断调整大小;
如果不支持连续布局,则拖动分割条时两边组件不会调整大小,而是只看到一条虚拟的分割条在移动,如图12.14所示。
这里有一张图片

默认不连续分布

JSplitPane默认关闭连续布局特性,因为使用连续布局需要不断重绘两边的组件,因此运行效率很低。

如何打开连续分布

如果需要打开指定JSplitPane面板的连续布局特性,则可以使用如下代码:

1
2
//打开JSplitPane的连续布局特性
jSplitPane.setContinuousLayout(true);

一键展开特性

除此之外,正如图12.13中看到的,上下分割面板的分割条中还有两个三角箭头,这两个箭头被称为“一触即展”键,当用户单击某个三角箭头时,将看到箭头所指的组件慢慢缩小到没有,而另一个组件则扩大到占据整个面板。如果需要打开“一触即展”特性,使用如下代码即可:

1
2
//打开“一触即展”特性
jSplitPane.setOneTouchExpandable(true);
方法 描述
void setDividerLocation(double proportionalLocation) 设置分隔条的位置JSplitPane的某个百分比
void setDividerLocation(int location) 通过像素值设置分隔条的位置
void setDividerSize(int newSize) 通过像素值设置分隔条的大小
void setLeftComponent(Component comp) 将指定组件放置到分割面板的左边或者上面。
void setRightComponent(Component comp) 将指定组件放置到分割面板的右边或者下面。

程序

下面程序简单示范了JSplitPane的用法。

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
import java.awt.Dimension;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

class Book {
private String name;
private Icon ico;
private String desc;

public Book() {
}

public Book(String name, Icon ico, String desc) {
this.name = name;
this.ico = ico;
this.desc = desc;
}

// name的setter和getter方法
public void setName(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

// ico的setter和getter方法
public void setIco(Icon ico) {
this.ico = ico;
}

public Icon getIco() {
return this.ico;
}

// desc的setter和getter方法
public void setDesc(String desc) {
this.desc = desc;
}

public String getDesc() {
return this.desc;
}

public String toString() {
return name;
}
}

public class SplitPaneTest {
Book[] books = new Book[] { new Book("疯狂Java讲义", new ImageIcon("ico/java.png"), "国内关于Java编程最全面的图书\n看得懂,学得会"),
new Book("轻量级Java EE企业应用实战", new ImageIcon("ico/ee.png"), "SSH整合开发的经典图书,值得拥有"),
new Book("疯狂Android讲义", new ImageIcon("ico/android.png"), "全面介绍Android平台应用程序\n开发的各方面知识") };
JFrame jf = new JFrame("测试JSplitPane");
JList<Book> bookList = new JList<>(books);
JLabel bookCover = new JLabel();
JTextArea bookDesc = new JTextArea();

public void init() {
// 为三个组件设置最佳大小
bookList.setPreferredSize(new Dimension(150, 300));
bookCover.setPreferredSize(new Dimension(300, 150));
bookDesc.setPreferredSize(new Dimension(300, 150));
// 为下拉列表添加事件监听器
bookList.addListSelectionListener(event -> {
Book book = (Book) bookList.getSelectedValue();
bookCover.setIcon(book.getIco());
bookDesc.setText(book.getDesc());
});
// 创建一个垂直的分割面板,
// 将bookCover放在上面,将bookDesc放在下面, 支持连续布局
JSplitPane left = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, bookCover, new JScrollPane(bookDesc));
// 打开“一触即展”的特性
left.setOneTouchExpandable(true);
// 下面代码设置分割条的大小。
// left.setDividerSize(50);
// 设置该分割面板根据所包含组件的最佳大小来调整布局
left.resetToPreferredSizes();
// 创建一个水平的分割面板
// 将left组件放在左边,将bookList组件放在右边
JSplitPane content = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, bookList);
jf.add(content);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.pack();
jf.setVisible(true);
}

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

上面代码中粗体字代码创建了两个JSplitPane,其中一个水平分隔条支持连续布局,垂直不支持连续布局
运行上面程序,将可看到如图12.13所示的界面。
这里有一张图片