【Java学习笔记】53:JTree的使用(新选中事件和结点双击事件)
2018-02-06 15:26
441 查看
JTree是Swing里的一种树形结构,感觉有些场合能起到意想不到的作用。
一般要考虑的仅仅是叶子结点,所以可以把这个组件强制转换成叶子结点的数据类型,如DefaultMutableTreeNode标准树结点,然后使用isLeaf()方法可以判定它是不是叶子结点。
在经过这样的筛选后,已经确定它是叶子结点了,还需要知道这个结点到底是哪个结点。如果结点之间的名称各不相同的话,可以使用其toString()方法去判断这个结点对应的字符串,这有些特别,因为之前学过的组件明明是使用事件对象的getActionCommand()方法然后用equals()作字符串的比较的。
打开DefaultMutableTreeNode源码看一下,其构造器中传入的实际上是一个Object对象:
然后看一下它的toString()方法,实际就是在做这个构造时传入的Object对象的toString(),当然对象不存在时候要返回一个空串:
C Node
D Node
B Node
D Node
获得了TreePath路径对象后,就可以使用它的getLastPathComponent()获取这棵树上这条路径上的最后一个组件了,还是强制转换成结点类型然后做操作就可以了。
实际使用时,双击事件也往往只需要去捕获叶子结点的,只要和前面一样做一个isLeaf()判断就可以了,我这里没写。
需要注意的是,对某些空白处双击时,还是属于在树上触发了双击事件,然而getPathForLocation()肯定获取不到路径了,返回的是一个null,在后面对这个对象的操作都必须包含在判断非null中才行,否则对null取成员方法显然是错误的。
[Root Node, A Node, C Node]
C Node
[Root Node]
Root Node
[Root Node]
Root Node
[Root Node, B Node]
B Node
[Root Node, A Node]
A Node
[Root Node, A Node, D Node]
D Node
树结点新选中的事件
说是”新选中”而不是”选中”或”单击”,因为监听器实际上是在看选中者的某个值有没有改变,连续的选中不会触发这件事,单击也仅仅是”选中”的一条不必要的途径,这些都不会产生TreeSelectionEvent对象。简述
选中事件的监听比较方便,不能对每个结点注册监听器,只能对整棵树注册一个实现了TreeSelectionListener接口的监听器,然后实现其valueChanged()方法,在方法中用JTree对象的getLastSelectedPathComponent()方法可以获取当前选择的第一个结点中的最后一个路径组件。一般要考虑的仅仅是叶子结点,所以可以把这个组件强制转换成叶子结点的数据类型,如DefaultMutableTreeNode标准树结点,然后使用isLeaf()方法可以判定它是不是叶子结点。
在经过这样的筛选后,已经确定它是叶子结点了,还需要知道这个结点到底是哪个结点。如果结点之间的名称各不相同的话,可以使用其toString()方法去判断这个结点对应的字符串,这有些特别,因为之前学过的组件明明是使用事件对象的getActionCommand()方法然后用equals()作字符串的比较的。
打开DefaultMutableTreeNode源码看一下,其构造器中传入的实际上是一个Object对象:
/** * Creates a tree node with no parent, no children, but which allows * children, and initializes it with the specified user object. * * @param userObject an Object provided by the user that constitutes * the node's data */ public DefaultMutableTreeNode(Object userObject) { this(userObject, true); }
然后看一下它的toString()方法,实际就是在做这个构造时传入的Object对象的toString(),当然对象不存在时候要返回一个空串:
/** * Returns the result of sending <code>toString()</code> to this node's * user object, or the empty string if the node has no user object. * * @see #getUserObject */ public String toString() { if (userObject == null) { return ""; } else { return userObject.toString(); } }
程序
import javax.swing.JFrame; import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; //实现TreeSelectionListener接口以成为树的选中事件的监听器 class TestJTree extends JFrame implements TreeSelectionListener { JTree jt;// 为了对valueChanged()方法可见,在这里声明 TestJTree() { super("JTree的使用"); // DefaultMutableTreeNode是树结构中通用的结点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Node"); DefaultMutableTreeNode nodeA = new DefaultMutableTreeNode("A Node"); // 用结点之间add的方法来实现嵌套(建立树结点的父子关系) root.add(nodeA); root.add(new DefaultMutableTreeNode("B Node"));// 可以用匿名对象 DefaultMutableTreeNode nodeC = new DefaultMutableTreeNode("C Node");// 也可以创建了再add nodeA.add(nodeC); nodeA.add(new DefaultMutableTreeNode("D Node")); // 用实现了TreeModel接口的DefaultTreeModel类来指定树的根结点 DefaultTreeModel dtm = new DefaultTreeModel(root); // 用这个根结点就可以去建立JTree树了 jt = new JTree(dtm); jt.addTreeSelectionListener(this);// 为这棵树注册监听器 this.setBounds(700, 150, 250, 400); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.add(jt); this.setVisible(true); } @Override public void valueChanged(TreeSelectionEvent e) { if (e.getSource() == jt) // 如果是要相应的那棵树 { // 获取当前选择的第一个结点中的最后一个路径组件 DefaultMutableTreeNode dmt = (DefaultMutableTreeNode) jt.getLastSelectedPathComponent(); // 如果是叶子结点 if (dmt.isLeaf()) { String str = dmt.toString();// 叶子结点的字符串 // 判断 if (str.equals("B Node")) { System.out.println("B Node"); } else if (str.equals("C Node")) { System.out.println("C Node"); } else if (str.equals("D Node")) { System.out.println("D Node"); } } } } } public class Main { public static void main(String[] args) { TestJTree tj = new TestJTree(); } }
运行结果
(新选中叶结点时会打印相应的字符串)C Node
D Node
B Node
D Node
树结点双击的事件
因为不能为树中的结点注册监听器,双击的事件也是为JTree对象注册的监听器。简述
查了好久,发现JTree对象有一个非常实用的的方法getPathForLocation()能够根据指定的坐标点来获取点击的那个结点在树中的逻辑路径TreePath对象。有了这个方法就不需要去手工判断点击的位置处是哪个对象了。获得了TreePath路径对象后,就可以使用它的getLastPathComponent()获取这棵树上这条路径上的最后一个组件了,还是强制转换成结点类型然后做操作就可以了。
实际使用时,双击事件也往往只需要去捕获叶子结点的,只要和前面一样做一个isLeaf()判断就可以了,我这里没写。
需要注意的是,对某些空白处双击时,还是属于在树上触发了双击事件,然而getPathForLocation()肯定获取不到路径了,返回的是一个null,在后面对这个对象的操作都必须包含在判断非null中才行,否则对null取成员方法显然是错误的。
程序
import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; class TestJTree extends JFrame { TestJTree() { super("JTree的使用"); // DefaultMutableTreeNode是树结构中通用的结点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Node"); DefaultMutableTreeNode nodeA = new DefaultMutableTreeNode("A Node"); // 用结点之间add的方法来实现嵌套(建立树结点的父子关系) root.add(nodeA); root.add(new DefaultMutableTreeNode("B Node"));// 可以用匿名对象 DefaultMutableTreeNode nodeC = new DefaultMutableTreeNode("C Node");// 也可以创建了再add nodeA.add(nodeC); nodeA.add(new DefaultMutableTreeNode("D Node")); // 用实现了TreeModel接口的DefaultTreeModel类来指定树的根结点 DefaultTreeModel dtm = new DefaultTreeModel(root); // 用这个根结点就可以去建立JTree树了 JTree jt = new JTree(dtm); // 为这棵树注册监听器,用匿名的适配器覆写鼠标点击方法 jt.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { // 如果在这棵树上点击了2次,即双击 if (e.getSource() == jt && e.getClickCount() == 2) { // 按照鼠标点击的坐标点获取路径 TreePath selPath = jt.getPathForLocation(e.getX(), e.getY()); if (selPath != null)// 谨防空指针异常!双击空白处是会这样 { System.out.println(selPath);// 输出路径看一下 // 获取这个路径上的最后一个组件,也就是双击的地方 DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent(); System.out.println(node.toString());// 输出这个组件toString()的字符串看一下 } } } }); this.setBounds(700, 150, 250, 400); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.add(jt); this.setVisible(true); } } public class Main { public static void main(String[] args) { TestJTree tj = new TestJTree(); } }
运行结果
[Root Node, A Node, C Node]
C Node
[Root Node]
Root Node
[Root Node]
Root Node
[Root Node, B Node]
B Node
[Root Node, A Node]
A Node
[Root Node, A Node, D Node]
D Node
相关文章推荐
- Java 学习笔记 (9) - Java 事件机制 内部匿名类的应用
- 学习使用J2EE Web应用的事件功能-Java基础-Java-编程开发
- Java学习笔记---9.面向对象编程04-this关键字的使用
- java学习笔记---第8章事件处理
- Effective C# 学习笔记(四十三)使用Expression处理绑定(属性值更改)事件
- 自定义控件学习笔记(5):事件委托列表的使用
- Java开发学习笔记之十:servlet事件
- (JAVA SE 学习笔记)Java.SE.第003讲.原生数据类型使用陷阱.Pitfall.of.Primitive.Data.Type
- [Java Path Finder][JPF学习笔记][8]几篇使用JPF的论文
- JavaScript学习笔记——事件(转自:http://www.blogjava.net/amigoxie/archive/2007/08/27/139711.html)
- [Java Path Finder][JPF学习笔记][8]几篇使用JPF的论文
- Java Swing中使用双击事件
- Java学习笔记之swing 单击事件mouseClicked与一般事件actionPerformed区别
- 【Java 学习笔记】 String.split使用心得
- ireport学习笔记---java应用程序中使用报表篇
- [Java Path Finder][JPF学习笔记][6]jpf-symbc的初步使用
- java学习笔记(四)----对象、数组作为参数传递,静态变量、静态方法的使用,内部类,使用文档注释
- [Java Path Finder][JPF学习笔记][3]使用jpf-shell
- 窗口关闭 事件处理 -Java学习笔记(36)
- java-使用keytool来创建管理密钥及证书等-java学习笔记(3)