TWaver - 專注UI技術(shù)

          http://twaver.servasoft.com/
          posts - 171, comments - 191, trackbacks - 0, articles - 2
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2012年11月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          新聞檔案(1)

          相冊

          搜索

          •  

          最新評論

          JTree實現(xiàn)文件樹

          Posted on 2012-11-02 15:20 TWaver 閱讀(2489) 評論(0)  編輯  收藏
          這篇文章介紹的內(nèi)容其實跟TWaver的組件沒有任何關(guān)系,但是個人覺得還是挺有意思的,所以發(fā)出來共享一下。這個文件樹(如下圖)完全基于swing的JTree組件實現(xiàn),先看一下最后我們完成的效果:

          運行截圖:



          功能介紹:

          • 樹狀呈現(xiàn)文件系統(tǒng)結(jié)構(gòu)
          • 文件的圖標(biāo)應(yīng)該使用系統(tǒng)圖標(biāo)
          • 鼠標(biāo)滑過時改變當(dāng)前節(jié)點的背景色(如圖中"Windows"節(jié)點的磚紅色背景)
          先看一下類結(jié)構(gòu):
          • FileTreeTest 程序入口
          • FileTree 文件樹,從JTree繼承
          • FileNode 封裝的文件節(jié)點,包括文件名,文件圖標(biāo)和實際的File類及其它標(biāo)識
          • FileTreeRenderer 定制的節(jié)點渲染器,從DefaultTreeCellRenderer繼承
          • FileTreeModel 定制的TreeModel,從DefaultTreeModel繼承
          考慮到系統(tǒng)文件會很多,在程序開始就初始化整個樹是不現(xiàn)實的,所以我采取一種延遲加載的策略,只有當(dāng)要展開某個節(jié)點的時候,才去初始化它的子節(jié)點,在FileTree的構(gòu)造里加一個監(jiān)聽:

           1 addTreeWillExpandListener(new TreeWillExpandListener() {
           2             @Override
           3             public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
           4                 DefaultMutableTreeNode lastTreeNode =
           5 (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
           6                 FileNode fileNode = (FileNode) lastTreeNode.getUserObject();
           7                 if (!fileNode.isInit) {
           8                     File[] files;
           9                     if (fileNode.isDummyRoot) {
          10                         files = fileSystemView.getRoots();
          11                     } else {
          12                         files = fileSystemView.getFiles(
          13                                 ((FileNode) lastTreeNode.getUserObject()).file,
          14                                 false);
          15                     }
          16                     for (int i = 0; i < files.length; i++) {
          17                        //文件名和圖標(biāo)都是通過fileSystemView得到
          18                         FileNode childFileNode = new FileNode(
          19                                 fileSystemView.getSystemDisplayName(files[i]),
          20                                 fileSystemView.getSystemIcon(files[i]), files[i],
          21                                 false);
          22                         DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(childFileNode);
          23                         lastTreeNode.add(childTreeNode);
          24                     }
          25                     //通知模型節(jié)點發(fā)生變化
          26                     DefaultTreeModel treeModel1 = (DefaultTreeModel) getModel();
          27                     treeModel1.nodeStructureChanged(lastTreeNode);
          28                 }
          29                 //更改標(biāo)識,避免重復(fù)加載
          30                 fileNode.isInit = true;
          31             }
          32             @Override
          33             public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
          34 
          35             }
          36         });

          當(dāng)然這種方式需要TableModel的配合,我重載了DefaultTreeModel,在構(gòu)造里初始化根節(jié)點,然后重載isLeaf方法,具體代碼可以下載附件查看。

          接下來思考一下鼠標(biāo)滑過改變背景色怎么實現(xiàn)。
          寫這段代碼的時候,我想起來了我剛學(xué)Renderer的時候的一個錯誤的認(rèn)識:誤以為每個節(jié)點都有一個Renderer并且妄圖在Renderer上加監(jiān)聽!在此強調(diào)一下:Renderer只是一個渲染器,要顯示節(jié)點的時候,JTree就調(diào)用它渲染并畫到屏幕上,但是無論有多少節(jié)點,一個JTree只有一個Renderer!
          Renderer上加監(jiān)聽行不通,我們就轉(zhuǎn)換一下思路,在JTree上加鼠標(biāo)move監(jiān)聽,然后repaint鼠標(biāo)所在的節(jié)點。

           1 addMouseMotionListener(new MouseAdapter() {
           2             @Override
           3             public void mouseMoved(MouseEvent e) {
           4 //獲得鼠標(biāo)所在的TreePath
           5                 TreePath path=getPathForLocation(e.getX(), e.getY());
           6 
           7 //計算repaint的區(qū)域并repaint JTree
           8                 if(path!=null){
           9                     if(mouseInPath!=null){
          10                         Rectangle oldRect=getPathBounds(mouseInPath);
          11                         mouseInPath=path;
          12                         repaint(getPathBounds(path).union(oldRect));
          13                     }else{
          14                         mouseInPath=path;
          15                         Rectangle bounds=getPathBounds(mouseInPath);
          16                         repaint(bounds);
          17                     }
          18                 }else if(mouseInPath!=null){
          19                     Rectangle oldRect=getPathBounds(mouseInPath);
          20                     mouseInPath=null;
          21                     repaint(oldRect);
          22                 }
          23             }
          24         });

          需要在JTree中保存鼠標(biāo)滑過的TreePath(mouseInPath),這樣在Renderer中才可以改變mouseInPath的背景色

           1 FileTree fileTree=(FileTree)tree;
           2         JLabel label= (JLabel) super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);
           3 
           4         DefaultMutableTreeNode node=(DefaultMutableTreeNode)value;
           5         FileNode fileNode=(FileNode)node.getUserObject();
           6         label.setText(fileNode.name);
           7         label.setIcon(fileNode.icon);
           8 
           9         label.setOpaque(false);
          10 //如果當(dāng)前渲染的節(jié)點就是鼠標(biāo)滑過的節(jié)點,改變背景色
          11         if(fileTree.mouseInPath!=null&&
          12                 fileTree.mouseInPath.getLastPathComponent().equals(value)){
          13             label.setOpaque(true);
          14             label.setBackground(new Color(255,0,0,90));
          15         }
          16         return label;

          至此這個文件樹就寫完了!全部代碼在附件,有興趣的同學(xué)可以下載看看,也希望看過的同學(xué)有好的想法來交流一下。 附件:見原文最下方

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 盘锦市| 平南县| 汉阴县| 曲松县| 镇康县| 邹平县| 安图县| 广宗县| 涟水县| 凌云县| 商水县| 大同县| 车险| 广宗县| 泗水县| 株洲县| 新宁县| 泸定县| 武穴市| 长寿区| 南城县| 五峰| 兴安县| 喜德县| 兴安盟| 镇沅| 江达县| 平湖市| 陵水| 石城县| 喀喇| 益阳市| 林芝县| 甘南县| 南部县| 和静县| 焉耆| 舟山市| 麦盖提县| 定南县| 兴宁市|