12.3.2 使用JTabbledPane 标签页

12.3.2 使用JTabbledPane 标签页

JTabbledPane可以很方便地在窗口上放置多个标签页,每个标签页相当于获得了一个与外部容器具有相同大小的组件摆放区域。通过这种方式,就可以在一个容器里放置更多的组件,例如右击桌面上的我的电脑”图标,在弹出的快捷菜单里单击“属性”菜单项,就可以看到一个“系统属性”对话框,这个对话框里包含了7个标签页。

创建标签页的步骤

如果需要使用JTabbedPane在窗口上创建标签页,则可以按如下步骤进行。

1 创建JTabbedPane对象

创建一个JTabbedPane对象,JTabbedPane提供了几个重载的构造器

方法 描述
JTabbedPane() Creates an empty TabbedPane with a default tab placement of JTabbedPane.TOP.
JTabbedPane(int tabPlacement) Creates an empty TabbedPane with the specified tab placement of either: JTabbedPane.TOP, JTabbedPane.BOTTOM, JTabbedPane.LEFT, or JTabbedPane.RIGHT.
JTabbedPane(int tabPlacement, int tabLayoutPolicy) Creates an empty TabbedPane with the specified tab placement and tab layout policy.

这些构造器里一共包含如下两个参数。

  • tabPlacement:该参数指定标签页标题的放置位置,例如前面介绍的“系统属性”对话框里标签页的标题放在窗口顶部。Swing支持将标签页标题放在窗口的4个方位:
    • JTabbedPane.TOP(顶部)、
    • JTabbedPane.LEFT(左边)、
    • JTabbedPane.BOTTOM(下部)
    • JTabbedPane.RIGHT(右边)
  • tabLayoutPolicy:指定标签页标题的布局策略。当窗口不足以在同一行摆放所有的标签页标题时Swing有两种处理方式:
    • 将标签页标题换行(JTabbedPane.WRAP_TAB_LAYOUT )排列
    • 使用滚动条来控制标签页标题的显示(JTabbedPane.SCROLL_TAB_LAYOUT)。

例如,下面代码创建一个JTabbedPane对象,该JTabbedPane的标签页标题位于窗口左侧,当窗口的一行不能摆放所有的标签页标题时,JTabbedPane将采用换行方式来排列标签页标题:

1
JTabbedPane tabPane = new JTabbedPane (JTabbedPane.LEFT,JTabbedPane.WRAP_TAB_LAYOUT);

2 增加 插入 修改 删除 标签页

调用JTabbedPane对象的addAbb()insertTab()setComponentAt()removeSabAt()方法来增加、插入、修改和删除标签页。其中

增加标签页

addAbb()方法总是在最前面增加标签页:

方法 描述
void addTab(String title, Component component) Adds a component represented by a title and no icon.
void addTab(String title, Icon icon, Component component) Adds a component represented by a title and/or icon, either of which can be null.
void addTab(String title, Icon icon, Component component, String tip) Adds a component and tip represented by a title and/or icon, either of which can be null.

添加标签页时可以指定该标签页的标题(title)、图标(icon,以及该Tab页面的组件(component)及提示信息(tip),这4个参数都可以是null:如果某个参数是null,则对应的内容为空。

不要使用add方法来添加标签页

不要使用JTabbedPaneadd()方法来添加组件,该方法是JTabbedPane重写Containner容器中的add方法,如果使用该ad()方法来添加Tab页面,毎次添加的标签页会直接覆盖原有的标签页。

插入 修改 删除标签页

insertTab()表示在指定位置插入标签页、setComponentAt()修改指定位置的标签页,removeTabAt()方法删除指定位置的标签页。

方法 描述
void insertTab(String title, Icon icon, Component component, String tip, int index) Inserts a new tab for the given component, at the given index, represented by the given title and/or icon, either of which may be null.
void setComponentAt(int index, Component component) Sets the component at index to component.
void removeTabAt(int index) Removes the tab at index.

先将组建放到容器中 再讲容器放到标签页中

不管使用增加、插入、修改哪种操作来改变JTabbedPane中的标签页,都是传入一个Component组件作为标签页。也就是说,如果希望在某个标签页内放置更多的组件,则必须先将这些组件放置到个容器(例如JPanel)里,然后将该容器设置为JTabbedPane指定位置的组件

3 显示某个标签页

如果需要让某个标签页显示出来,则可以通过调用JTabbedPanesetSelectedIndex()方法来实现:

方法 描述
void setSelectedIndex(int index) Sets the selected index for this tabbedpane.

例如如下代码

1
2
3
4
// 设置第三个Tab页面处于显示状态
tabPane.setSelectedIndex(2);
//设置最后一个Tab页面处于显示状态
tabPane.setSelectedIndex(tabPanel.getTabCount()-1);

4 操作JTabbedPane属性

程序还可通过JTabbedPane提供的一系列方法来操作JTabbedPane的相关属性。例如,有如下几个常用方法

方法 描述
void setDisabledIconAt(int index, Icon disabledIcon) 将指定位置的禁用图标设置为icon,该图标也可以是null,表示不使用禁用图标。
void setEnabledAt(int index, boolean enabled) 设置指定位置的标签页是否启用。
void setForegroundAt(int index, Color foreground) 设置指定位置标签页的前景色为foreground。该颜色可以是nul,这时将使用该JTabbedPane的前景色作为此标签页的前景色。
void setIconAt(int index, Icon icon) 设置指定位置标签页的图标。
void setTitleAt(int index, String title) 设置指定位置标签页的标题为title,该title可以是null,这表明设置该标签页的标题为空。
void setToolTipTextAt(int index, String toolTipText) 设置指定位置标签页的提示文本。

5 监听标签页事件

如果程序需要监听用户单击标签页的事件,例如,当用户单击某个标签页时才载入该标签页的内容,则可以使用ChangeListener监听器来监听JTabbedPane对象

例如如下代码:

1
tabPane.addChangeListener(listener);

当用户单击标签页时,系统将把该事件封装成ChangeEvent对象,并作为参数来触发ChangeListener里的stateChanged事件处理器方法:

方法 描述
void stateChanged(ChangeEvent e) Invoked when the target of the listener has changed its state.

程序 标签页

下面程序定义了具有5个标签页的JTabbedPane面板,该程序可以让用户选择标签布局策略、标签位置。

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
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;

public class JTabbedPaneTest {
JFrame jf = new JFrame("测试Tab页面");
// 创建一个Tab页面的标签放在左边,采用换行布局策略的JTabbedPane
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT, JTabbedPane.WRAP_TAB_LAYOUT);
ImageIcon icon = new ImageIcon("ico/close.gif");
String[] layouts = { "换行布局", "滚动条布局" };
String[] positions = { "左边", "顶部", "右边", "底部" };
Map<String, String> books = new LinkedHashMap<>();

public void init() {
books.put("疯狂Java讲义", "java.png");
books.put("轻量级Java EE企业应用实战", "ee.png");
books.put("疯狂Ajax讲义", "ajax.png");
books.put("疯狂Android讲义", "android.png");
books.put("经典Java EE企业应用实战", "classic.png");
String tip = "可看到本书的封面照片";
// 向JTabbedPane中添加5个标签页面,指定了标题、图标和提示
// 但该标签页面的组件为null
for (String bookName : books.keySet()) {
tabbedPane.addTab(bookName, icon, null, tip);
}
jf.add(tabbedPane, BorderLayout.CENTER);
// 为JTabbedPane添加事件监听器
tabbedPane.addChangeListener(event -> {
// 如果被选择的组件依然是空
if (tabbedPane.getSelectedComponent() == null) {
// 获取所选标签页
int n = tabbedPane.getSelectedIndex();
// 为指定标前页加载内容
loadTab(n);
}
});
// 系统默认选择第一页,加载第一页内容
loadTab(0);
tabbedPane.setPreferredSize(new Dimension(500, 300));
// 增加控制标签布局、标签位置的单选按钮
JPanel buttonPanel = new JPanel();
ChangeAction action = new ChangeAction();
buttonPanel.add(new ButtonPanel(action, "选择标签布局策略", layouts));
buttonPanel.add(new ButtonPanel(action, "选择标签位置", positions));
jf.add(buttonPanel, BorderLayout.SOUTH);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.pack();
jf.setVisible(true);
}

// 为指定标签页加载内容
private void loadTab(int n) {
String title = tabbedPane.getTitleAt(n);
// 根据标签页的标题获取对应图书封面
ImageIcon bookImage = new ImageIcon("ico/" + books.get(title));
tabbedPane.setComponentAt(n, new JLabel(bookImage));
// 改变标签页的图标
tabbedPane.setIconAt(n, new ImageIcon("ico/open.gif"));
}

// 定义改变标签页的布局策略,放置位置的监听器
class ChangeAction implements ActionListener {
public void actionPerformed(ActionEvent event) {
JRadioButton source = (JRadioButton) event.getSource();
String selection = source.getActionCommand();
// 设置标签页的标题的布局策略
if (selection.equals(layouts[0])) {
tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
} else if (selection.equals(layouts[1])) {
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
}
// 设置标签页上的标题的放置位置
else if (selection.equals(positions[0])) {
tabbedPane.setTabPlacement(JTabbedPane.LEFT);
} else if (selection.equals(positions[1])) {
tabbedPane.setTabPlacement(JTabbedPane.TOP);
} else if (selection.equals(positions[2])) {
tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
} else if (selection.equals(positions[3])) {
tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
}
}
}

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

// 定义一个JPanel类扩展类,该类的对象包含多个纵向排列的JRadioButton控件
// 且JPanel扩展类可以指定一个字符串作为TitledBorder
class ButtonPanel extends JPanel {
private static final long serialVersionUID = -6408828937684129034L;
private ButtonGroup group;

public ButtonPanel(JTabbedPaneTest.ChangeAction action, String title, String[] labels) {
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
group = new ButtonGroup();
for (int i = 0; labels != null && i < labels.length; i++) {
JRadioButton b = new JRadioButton(labels[i]);
b.setActionCommand(labels[i]);
add(b);
// 添加事件监听器
b.addActionListener(action);
group.add(b);
b.setSelected(i == 0);
}
}
}

程序运行后会看到如图12.15所示的标签页效果