0.前言
最近老師佈置了一項用Java寫資源管理器的任務,一開始覺得簡單,可是實際操做起來,卻發現網上的資源用起來相對生疏。在使用中,我也遇到了許多問題,雖然不能像其餘博主同樣,寫的很是齊全,但我仍是分享一下我寫的代碼。java
1.準備知識
- JTree是樹形結構,是咱們作資源管理器的必要組件。其構造函數的參數能夠是節點,或者樹模型。
- JTree只有放在JScrollPane裏,才能夠很好的顯示(由於有時候樹很大,要拉很長才能看到),固然不放也能夠。
- JTree是經過增長節點,來實現多層目錄的。
- 通常使用DefaultMutableTreeNode來實現節點,能夠經過add()函數,添加孩子節點。
- 還有些瑣碎的知識點,會在第三部分一一講述。
2.思路
一開始的思路是用DFS深搜,可是實現後發現,至關的慢。node
因此,我就想先寫一個「個人電腦」節點,而後往下加磁盤分區,而後當我點擊一個節點的時候(用事件監聽,這裏用到TreeSelectionListener),再往下展開(添加節點)git
3.分段代碼
1.獲取系統的磁盤目錄
1 //獲取磁盤目錄 2 File roots[] = File.listRoots(); 3 //添加至父節點 4 for(int i=0; i<roots.length; 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&&jsp
1 TreeNode[] tn= node.getPath(); 2 String path = tn[1].toString(); 3 for(int i=2; i<tn.length; i++) { 4 path += tn[i] + "\\"; 5 }
4.將TreePath轉化成String
&&TreePath和TreeNode有點類似,可是TreePath沒法逐一獲取元素,須要先用函數getPath()轉換成Object而後在轉換成String&&ide
1 //path的類型是TreePath 2 Object tmp[] = path.getPath(); 3 String tmp_path = tmp[1].toString(); 4 for(int i=2; i<tmp.length; 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.所有代碼
【在對節點操做時,必定要先選中節點】佈局
實現的節點操做功能:複製;粘貼;刪除學習
但願你們不要徹底抄錄,有所思考,不會的地方,能夠在下方評論,我會盡我可能解答,和你們一塊兒學習!this
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<roots.length; 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<childs.length; 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<tp.length; 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<tmp.length; 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 }