12.10.3 监听节点事件

12.10.3 监听节点事件

JTree专门提供了一个TreeSelectionModel对象来保存该JTree选中状态的信息。也就是说,JTree组件背后隐藏了两个model对象,其中TreeModel用于保存该JTree的所有节点数据,而TreeSelectionModel用于保存该JTree的所有选中状态的信息

TreeSelectionModel

对于大部分开发者而言,无须关心TreeSelectionModel的存在,程序可以通过JTree提供的getSelectionPath()方法和getSelectionPaths方法来获取该JTree被选中的TreePath,但实际上这两个方法底层实现依然依赖于TreeSelectionModel,只是普通开发者一般无须关心这些底层细节而已。

改变JTree的选择模式

程序可以改变JTree的选择模式,但必须先获取该JTree对应的TreeSelectionModel对象,再调用该对象的setSelectionModel()方法来设置该JTree的选择模式。setSelectionMode方法支持如下三个参数。

  • TreeSelectionModel_CONTIGUOUS_TREE_SELECTION:可以连续选中多个TreePath
  • TreeSelectionModel_DISCONTIGUOUS_TREE_SELECTION:该选项对于选择没有任何限制。
  • TreeSelectionModel_DISCONTIGUOUS_TREE_SELECTION:每次只能选择一个TreePath
方法 描述
void setSelectionMode(int mode) Sets the selection model, which must be one of SINGLE_TREE_SELECTION, CONTIGUOUS_TREE_SELECTION or DISCONTIGUOUS_TREE_SELECTION.

JList操作类似,按下Ctrl辅助键,用于添加选中多个JTree节点:按下Shift辅助键,用于选择连续区域里的所有JTree节点。

方法 描述
void addTreeExpansionListener(TreeExpansionListener tel) 添加树节点展开/折叠事件的监听器
void addTreeSelectionListener(TreeSelectionListener tsl) 添加树节点选择事件的监听器

程序

下面程序设置JTree只能选择单个TreePath,并为节点选择事件添加事件监听器。

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
import javax.swing.*;
import javax.swing.tree.*;

public class SelectJTree {
JFrame jf = new JFrame("监听树的选择事件");
JTree tree;
// 定义几个初始节点
DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");
JTextArea eventTxt = new JTextArea(5, 20);

public void init() {
// 通过add()方法建立树节点之间的父子关系
guangdong.add(foshan);
guangdong.add(shantou);
guangxi.add(guilin);
guangxi.add(nanning);
root.add(guangdong);
root.add(guangxi);
// 以根节点创建树
tree = new JTree(root);
// 设置只能选择一个TreePath
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
// 添加监听树节点选择事件的监听器
// 当JTree中被选择节点发生改变时,将触发该方法
tree.addTreeSelectionListener(e -> {
if (e.getOldLeadSelectionPath() != null)
eventTxt.append("原选中的节点路径:" + e.getOldLeadSelectionPath().toString() + "\n");
eventTxt.append("新选中的节点路径:" + e.getNewLeadSelectionPath().toString() + "\n");
});
// 设置是否显示根节点的“展开/折叠”图标,默认是false
tree.setShowsRootHandles(true);
// 设置根节点是否可见,默认是true
tree.setRootVisible(true);
Box box = new Box(BoxLayout.X_AXIS);
box.add(new JScrollPane(tree));
box.add(new JScrollPane(eventTxt));
jf.add(box);
jf.pack();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}

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

上面程序中设置了该JTree对象采用SINGLE_TREE_SELECTION选择模式,即每次只能选中该JTree的一个TreePath。第二段粗体字代码为该JTree添加了个节点选择事件的监听器,当该JTre中被选择节点发生改变时,该监听器就会被触发。运行上面程序,会看到如图12.43所示的效
果。

不要通过监听鼠标事件来监听所选节点的变化,因为JTree中节点的选择完全可以通过键盘来操作,不通过鼠标单击亦可