0.前言
最近老师布置了一项用Java写资源管理器的任务,一开始以为简单,但是实际操作起来,却发现网上的资源用起来相对生疏。在使用中,我也遇到了许多问题,虽然不能像其他博主一样,写的非常齐全,但我还是分享一下我写的代码。
1.准备知识
- JTree是树形结构,是我们做资源管理器的必要组件。其构造函数的参数可以是节点,或者树模型。
- JTree只有放在JScrollPane里,才可以很好的显示(因为有时候树很大,要拉很长才能看到),当然不放也可以。
- JTree是通过增加节点,来实现多层目录的。
- 一般使用DefaultMutableTreeNode来实现节点,可以通过add()函数,添加孩子节点。
- 还有些琐碎的知识点,会在第三部分一一讲述。
2.思路
一开始的思路是用DFS深搜,但是实现后发现,相当的慢。
所以,我就想先写一个“我的电脑”节点,然后往下加磁盘分区,然后当我点击一个节点的时候(用事件监听,这里用到TreeSelectionListener),再往下展开(添加节点)
3.分段代码
1.获取系统的磁盘目录
1 //获取磁盘目录 2 File roots[] = File.listRoots(); 3 //添加至父节点 4 for(int i=0; i) { 5 father_node.add(new DefaultMutableTreeNode(roots[i])); 6 }
2.设置一颗完好的树,并加入面板
&&强调&&一定要先把Tree设置好之后,再添加至JScrollPane上,否则可能会出现无显示的情况&&
1 //设置树的模式,也可以不设置 2 DefaultMutableTreeNode top_node= new DefaultMutableTreeNode("我的电脑"); 3 DefaultTreeModel treeModel = new DefaultTreeModel(top); 4 //设置树 5 JTree tree = new JTree(treeModel); //可以直接用节点初始化 6 tree.setEditable(true); //设置可以编辑节点名 7 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);//设置仅单选 8 tree.setShowsRootHandles(true); 9 //将树添加至面板 10 JScrollPane jsp = new JScrollPane(tree); 11 jsp.setPreferredSize(new Dimension(200, 405)); 12 JPanel jpl = new JPanel(); 13 jpl.add(jsp);
3.将TreeNode转化成String
&&TreeNode获得到的是一个列表,其中有各个节点的名字。应该是没有办法直接转换成路径的,我查了好多资料,所有就先转换成String然后在转换成File&&
1 TreeNode[] tn= node.getPath(); 2 String path = tn[1].toString(); 3 for(int i=2; i) { 4 path += tn[i] + "\\"; 5 }
4.将TreePath转化成String
&&TreePath和TreeNode有点相似,但是TreePath无法逐一获取元素,需要先用函数getPath()转换成Object然后在转换成String&&
1 //path的类型是TreePath 2 Object tmp[] = path.getPath(); 3 String tmp_path = tmp[1].toString(); 4 for(int i=2; i) { 5 tmp_path += tmp[i] + "\\"; 6 }
5.事件处理中获取当前的节点
1 public void valueChanged(TreeSelectionEvent e) { 2 DefaultMutableTreeNode node = (DefaultMutableTreeNode) (e.getPath().getLastPathComponent()); 3 }
6.直接使用updateUI()后,点击节点报错问题
&&多线程&&这里涉及到了多线程的知识&&
1 SwingUtilities.invokeLater(new Runnable(){ 2 public void run(){ 3 tree.updateUI(); 4 }});
4.全部代码
【在对节点操作时,一定要先选中节点】
实现的节点操作功能:复制;粘贴;删除
希望大家不要完全抄录,有所思考,不会的地方,可以在下方评论,我会尽我可能解答,和大家一起学习!
gitee可下载源码:https://gitee.com/XiaoLuBanBi/codes/mqtvn5iaj8ehlbgorpwdx44
1 import java.awt.*; 2 import java.awt.event.ActionEvent; 3 import java.awt.event.ActionListener; 4 import java.awt.event.MouseEvent; 5 import java.awt.event.MouseListener; 6 import java.io.File; 7 8 import javax.swing.*; 9 import javax.swing.event.TreeSelectionEvent; 10 import javax.swing.event.TreeSelectionListener; 11 import javax.swing.filechooser.FileSystemView; 12 import javax.swing.tree.*; 13 14 /** 15 * 对节点进行操作时,一定要先选中节点 16 * @author a1126 17 * 18 */ 19 public class Src_manage extends JFrame 20 implements TreeSelectionListener, MouseListener, ActionListener { 21 //设置树结构 22 private JTree tree = new JTree(); 23 private DefaultTreeModel treeModel; 24 private DefaultMutableTreeNode top; 25 //设置右击菜单项 26 private JPopupMenu jp = new JPopupMenu(); 27 private JMenuItem copy = new JMenuItem("复制"); 28 private JMenuItem paste = new JMenuItem("粘贴"); 29 private JMenuItem delete = new JMenuItem("删除"); 30 //设置复制黏贴临时存储 31 private File copy_path = null; 32 private File now_path = null; 33 private DefaultMutableTreeNode now_node = null; 34 35 /** 36 * 构造函数 37 */ 38 public Src_manage() { 39 //设置布局 40 this.setLayout(new BorderLayout()); 41 this.add(createPC(), BorderLayout.CENTER); 42 this.add(createPW(), BorderLayout.WEST); 43 ini_right_click(); 44 //设置窗体 45 this.setSize(550, 450); //设置大小 46 this.setVisible(true); //设置窗体可见 47 this.setTitle("资源管理器"); //设置标题 48 this.setResizable(false); //设置不允许缩放 49 setLocationRelativeTo(null); //窗口居中 50 setDefaultCloseOperation(EXIT_ON_CLOSE);//窗口点击关闭时,退出程序 51 } 52 /** 53 * 设置西边面板 54 * @return 55 */ 56 public JPanel createPW() { 57 JPanel pw = new JPanel(); 58 //设置树的模式,也可以不设置 59 top = new DefaultMutableTreeNode("我的电脑"); 60 treeModel = new DefaultTreeModel(top); 61 //设置树 62 tree = new JTree(treeModel); //可以直接用节点初始化 63 tree.setEditable(true); //设置可以编辑节点名 64 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);//设置仅单选 65 tree.setShowsRootHandles(true); 66 //设置监听 67 tree.addTreeSelectionListener(this); 68 tree.addMouseListener(this); 69 //设置磁盘节点,加在top上 70 File roots[] = File.listRoots(); 71 for(int i=0; i) { 72 top.add(new DefaultMutableTreeNode(roots[i])); 73 } 74 //添加至面板 75 JScrollPane jsp = new JScrollPane(tree); 76 jsp.setPreferredSize(new Dimension(200, 405)); 77 pw.add(jsp); 78 //返回 79 return pw; 80 } 81 /** 82 * 设置中部面板 83 * @return 84 */ 85 public JPanel createPC() { 86 return new JPanel(); 87 } 88 /** 89 * 创建节点 90 * @param path 文件路径 91 * @param node 默认节点 92 */ 93 public void createNode(File path, DefaultMutableTreeNode node) { 94 //如果是文件,则跳出 95 if(path.isFile()) 96 return; 97 //否则,获取子文件,创建子节点 98 File childs[] = path.listFiles(); 99 for(int i=0; i ) { 100 //如果是隐藏文件,则跳过 101 if(childs[i].isHidden()) 102 continue; 103 //根据文件名,创建节点 104 DefaultMutableTreeNode tmp = new DefaultMutableTreeNode(childs[i].getName()); 105 //加入树中 106 treeModel.insertNodeInto(tmp, node, node.getChildCount()); 107 //如果是文件夹,则创建空子节点(在后面会删掉) 108 if(childs[i].isDirectory()) 109 tmp.add(new DefaultMutableTreeNode()); 110 } 111 } 112 /** 113 * 初始化右键菜单 114 */ 115 public void ini_right_click() { 116 jp.add(copy); 117 jp.add(paste); 118 jp.add(delete); 119 copy.addActionListener(this); 120 paste.addActionListener(this); 121 delete.addActionListener(this); 122 } 123 /** 124 * 主函数 125 * @param args 126 */ 127 public static void main(String[] args) { 128 // TODO 自动生成的方法存根 129 new Src_manage(); 130 } 131 //选择节点时,往下更新子节点 132 @Override 133 public void valueChanged(TreeSelectionEvent e) { 134 // TODO 自动生成的方法存根 135 //获取选择的节点 136 DefaultMutableTreeNode node = (DefaultMutableTreeNode) (e.getPath().getLastPathComponent()); 137 now_node = node; 138 //若为根节点,跳出 139 if(node.isRoot()) 140 return; 141 //根据获取到的树中路径,创建磁盘绝对路径 142 TreeNode[] tp = node.getPath(); 143 String path = tp[1].toString(); 144 for(int i=2; i ) { 145 path += tp[i] + "\\"; 146 } 147 //删除子文件 148 node.removeAllChildren(); 149 SwingUtilities.invokeLater(new Runnable(){ 150 public void run(){ 151 tree.updateUI(); 152 }});//处理updateUI()抛空指针的问题 153 //调用 增加节点函数 154 createNode( new File(path), node); 155 } 156 @Override 157 public void mouseClicked(MouseEvent e) { 158 // TODO 自动生成的方法存根 159 //获取右击点的节点路径 160 TreePath path = tree.getPathForLocation(e.getX(), e.getY()); 161 //右击事件 162 if (e.getButton() == MouseEvent.BUTTON3 && path != null) { 163 // 确定当前节点 164 Object tmp[] = path.getPath(); 165 if(tmp.length == 1) //如果获取的字符串长度为1,即是最上一层,则跳出 166 return; 167 String tmp_path = tmp[1].toString(); 168 for(int i=2; i ) { 169 tmp_path += tmp[i] + "\\"; 170 } 171 now_path = new File(tmp_path); 172 // 弹出菜单 173 jp.show(e.getComponent(), e.getX(), e.getY()); 174 } 175 } 176 @Override 177 public void mouseEntered(MouseEvent e) { 178 // TODO 自动生成的方法存根 179 180 } 181 @Override 182 public void mouseExited(MouseEvent e) { 183 // TODO 自动生成的方法存根 184 185 } 186 @Override 187 public void mousePressed(MouseEvent e) { 188 // TODO 自动生成的方法存根 189 190 } 191 @Override 192 public void mouseReleased(MouseEvent e) { 193 // TODO 自动生成的方法存根 194 195 } 196 /** 197 * 实现右键功能 198 */ 199 @Override 200 public void actionPerformed(ActionEvent e) { 201 // TODO 自动生成的方法存根 202 if(e.getSource() == copy) { //复制按钮 203 copy_path = now_path; 204 }else if (e.getSource() == paste) { //粘贴按钮 205 now_node.add(new DefaultMutableTreeNode(copy_path.getName())); 206 //如果复制的节点下面还有子节点,也一起复制 207 if(copy_path.isDirectory()) 208 createNode(copy_path, now_node); 209 }else if(e.getSource() == delete) { //删除按钮 210 treeModel.removeNodeFromParent(now_node); 211 } 212 } 213 }