<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    TWaver - 專注UI技術

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

    JTree實現文件樹

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

    運行截圖:



    功能介紹:

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

     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                        //文件名和圖標都是通過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                     //通知模型節點發生變化
    26                     DefaultTreeModel treeModel1 = (DefaultTreeModel) getModel();
    27                     treeModel1.nodeStructureChanged(lastTreeNode);
    28                 }
    29                 //更改標識,避免重復加載
    30                 fileNode.isInit = true;
    31             }
    32             @Override
    33             public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
    34 
    35             }
    36         });

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

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

     1 addMouseMotionListener(new MouseAdapter() {
     2             @Override
     3             public void mouseMoved(MouseEvent e) {
     4 //獲得鼠標所在的TreePath
     5                 TreePath path=getPathForLocation(e.getX(), e.getY());
     6 
     7 //計算repaint的區域并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中保存鼠標滑過的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 //如果當前渲染的節點就是鼠標滑過的節點,改變背景色
    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;

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

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


    網站導航:
     
    主站蜘蛛池模板: 四虎影永久在线高清免费| 男女啪啪免费体验区| 久久这里只精品热免费99| 久久精品国产亚洲Aⅴ香蕉 | 亚洲国产精品人久久电影| 亚洲国产成人精品91久久久| 亚洲国产午夜精品理论片在线播放| 成年女性特黄午夜视频免费看 | 亚洲成AV人影片在线观看| 韩国欧洲一级毛片免费| 国产精品亚洲专区无码不卡| 免费观看午夜在线欧差毛片| 一本一道dvd在线观看免费视频 | 亚洲AV无码之日韩精品| a级毛片免费高清视频| 国产精品xxxx国产喷水亚洲国产精品无码久久一区| 美女视频免费看一区二区| 国产亚洲精品自在线观看| 国产精品99久久免费观看| 中文字幕亚洲综合久久2| 欧美三级在线电影免费| 国产av天堂亚洲国产av天堂| 99视频在线免费看| 亚洲中文字幕无码中文| 久久国产精品2020免费m3u8| 亚洲综合伊人制服丝袜美腿| 免费国产人做人视频在线观看| 精品97国产免费人成视频| 精品无码一区二区三区亚洲桃色| 最近最好的中文字幕2019免费| 男人免费视频一区二区在线观看| 亚洲国产精品一区第二页| 毛片a级毛片免费播放下载 | 亚洲免费视频播放| 亚洲第一区精品观看| 99热这里只有精品免费播放| 亚洲欧美日韩国产精品一区| 国产AⅤ无码专区亚洲AV| 一级毛片不卡免费看老司机| 亚洲精品免费在线观看| 国产伦精品一区二区三区免费下载|