<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 閱讀(2481) 評論(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;

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

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


    網站導航:
     
    主站蜘蛛池模板: 67pao强力打造67194在线午夜亚洲| 国产一二三四区乱码免费| 亚洲国产精品综合久久网各| 亚洲s色大片在线观看| 亚洲午夜未满十八勿入网站2| 亚洲第一成人影院| 免费又黄又硬又爽大片| 国产免费变态视频网址网站| 日韩高清免费观看| 日本黄色免费观看| 波多野结衣一区二区免费视频| 香蕉视频在线观看免费国产婷婷| 免费看无码自慰一区二区| 午夜一级毛片免费视频| 波多野结衣久久高清免费 | 亚洲国产精品无码久久久| 亚洲欧洲在线播放| 亚洲videos| 亚洲av永久无码天堂网| 国产成人亚洲精品播放器下载| 曰批免费视频播放免费| 一区二区三区视频免费观看| a毛片免费在线观看| 久久精品国产大片免费观看| 5g影院5g天天爽永久免费影院| 波多野结衣在线免费观看| 最近免费中文字幕4| 又大又粗又爽a级毛片免费看| 亚洲国产日韩成人综合天堂| 中文亚洲AV片在线观看不卡| 亚洲AV福利天堂一区二区三| 亚洲毛片免费观看| 亚洲国产精品精华液| 中美日韩在线网免费毛片视频| 一个人免费视频观看在线www| 日本xxxx色视频在线观看免费| 大学生一级毛片免费看| 免费h成人黄漫画嘿咻破解版| 亚洲人成色77777| 亚洲第一页中文字幕| 亚洲av成人一区二区三区在线播放|