zoukankan      html  css  js  c++  java
  • jtree(选择框)

    jtree一般的用法是:

    1. 展示电脑中文件的层次结构,如图所示.

    image

    具体的代码:

    package jtree;
    
    import java.io.File;
    
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    
    public class ZJtree extends JTree {
    
        private static final long serialVersionUID = -581164150235777786L;
        private static final String ROOT_NAME = "我的电脑";
        private static final int levelUp = 3;
        
         public ZJtree() {
            this.setModel(new DefaultTreeModel(createRootNode()));
        }
    
         public  DefaultMutableTreeNode createRootNode(){ 
              DefaultMutableTreeNode treeNode = null;
              DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(ROOT_NAME); 
              for(int i = 0; i < File.listRoots().length ; i++){ 
                  if(File.listRoots()[i].isDirectory()){ 
                      String rootPath = File.listRoots()[i].getPath(); 
                      treeNode  = creatDefaultMutableTreeNode(rootPath,0); 
                      rootNode.add(treeNode); 
                      treeNode = null;
                  } 
              } 
    
                return rootNode; 
            }
    
        private DefaultMutableTreeNode creatDefaultMutableTreeNode(String nodePath,int level) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(nodePath);
            DefaultMutableTreeNode treeNode = null;
            level = level+1;
            File file = new File(nodePath);
            if(file.isDirectory() && file.listFiles() != null){
                 for(int i = 0; i < file.listFiles().length && level < levelUp; i++){ 
                      if(file.listFiles()[i].isDirectory()){ 
                          String rootPath = file.listFiles()[i].getPath();
                          treeNode  = creatDefaultMutableTreeNode(rootPath,level); 
                          node.add(treeNode); 
                          treeNode = null; 
                      } 
                  }
            }
             
            return node;
        }
    
    }

    说明:限制层次的原因是因为电脑中文件过多,一直加载会比较的慢,以后我们会在处理这个问题。

    看到上面的那个界面的第一个反应,就是好丑啊,我们慢慢的优化。在树节点的选择上面,增加combox,一步一步的来。

    首先我们新建一个扩展自Jtree的自定义类:

    public class ZTreeCheckBox extends JTree {
    
        private static final long serialVersionUID = -581164150235777786L;
        private static final String ROOT_NAME = "p";
        private static final int levelUp = 3;
        
         public ZTreeCheckBox() {
            this.setModel(new DefaultTreeModel(createRootNode()));
            this.setCellRenderer(new ChectBoxTreeCellRender());
            this.addCheckSelectListender();
        }
    
         private void addCheckSelectListender() {
             this.addMouseListener(new CheckBoxTreeNodeListender(this));
        }
    
        public  CheckBoxTreeNode createRootNode(){ 
             CheckBoxTreeNode treeNode = null;
             CheckBoxTreeNode rootNode = new CheckBoxTreeNode(ROOT_NAME); 
              for(int i = 0; i < File.listRoots().length ; i++){ 
                  if(File.listRoots()[i].isDirectory()){ 
                      String rootPath = File.listRoots()[i].getPath(); 
                      treeNode  = creatDefaultMutableTreeNode(rootPath,0); 
                      rootNode.add(treeNode); 
                      treeNode = null;
                  } 
              } 
    
                return rootNode; 
            }
    
        private CheckBoxTreeNode creatDefaultMutableTreeNode(String nodePath,int level) {
            CheckBoxTreeNode node = new CheckBoxTreeNode(nodePath);
            CheckBoxTreeNode treeNode = null;
            level = level+1;
            File file = new File(nodePath);
            if(file.isDirectory() && file.listFiles() != null){
                 for(int i = 0; i < file.listFiles().length && level < levelUp; i++){ 
                      if(file.listFiles()[i].isDirectory()){ 
                          String rootPath = file.listFiles()[i].getPath();
                          treeNode  = creatDefaultMutableTreeNode(rootPath,level); 
                          node.add(treeNode); 
                          treeNode = null; 
                      } 
                  }
            }
             
            return node;
        }
    }

    tree 的数据的组织形式,还和原来一样,但是我们需要tree的节点的形式是Combox形式的,最起码前面要是一个可选的样子,所以我们自定义一个TreeCellRenderer,我们在显示的时候可以是一个Jpanel,其中包含一个combox,一个Jlabel代码如下:

    public class ChectBoxTreeCellRender extends JPanel implements
            TreeCellRenderer {
    
        private static final long serialVersionUID = 4676667399191240255L;
    
        
        protected JCheckBox check;
        protected CheckBoxTreeLabel label;
    //    protected JLabel label;
        public ChectBoxTreeCellRender() {
            setLayout(null);
            add(check = new JCheckBox());
            add(label = new CheckBoxTreeLabel());
    //        add(label = new JLabel());
            check.setBackground(UIManager.getColor("Tree.textBackground"));
            label.setForeground(UIManager.getColor("Tree.textForeground"));
            this.setPreferredSize(new Dimension(100, 20));
        }
        
        
        /* (non-Javadoc)
         * @see javax.swing.tree.TreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean)
         */
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value,
                boolean selected, boolean expanded, boolean leaf, int row,
                boolean hasFocus) {
            String stringValue = tree.convertValueToText(value, selected, expanded,
                    leaf, row, hasFocus);
            setEnabled(tree.isEnabled());
            check.setSelected(((CheckBoxTreeNode) value).isSelect());
            label.setFont(tree.getFont());
            label.setText(stringValue);
            label.setSelected(selected);
            label.setFocus(hasFocus);
            if (leaf)
                label.setIcon(UIManager.getIcon("Tree.leafIcon"));
            else if (expanded)
                label.setIcon(UIManager.getIcon("Tree.openIcon"));
            else
                label.setIcon(UIManager.getIcon("Tree.closedIcon"));
    
            return this;
        }
        @Override
        public void doLayout() {
            Dimension dCheck = check.getPreferredSize();
            Dimension dLabel = label.getPreferredSize();
            int yCheck = 0;
            int yLabel = 0;
            if (dCheck.height < dLabel.height)
                yCheck = (dLabel.height - dCheck.height) / 2;
            else
                yLabel = (dCheck.height - dLabel.height) / 2;
            check.setLocation(0, yCheck);
            check.setBounds(0, yCheck, dCheck.width, dCheck.height);
            label.setLocation(dCheck.width, yLabel);
            label.setBounds(dCheck.width, yLabel, dLabel.width, dLabel.height);
        }
    
        @Override
        public void setBackground(Color color) {
            if (color instanceof ColorUIResource)
                color = null;
            super.setBackground(color);
        }
    }

    关于选中了节点以后,label是否出现阴影表示选择,在这里不是重点,这个扩展CheckBoxTreeLabel,会放在git上,现在我们关注的是Jlabel和Combox的结合而成的JPanel。

    现在我们还缺少一个选择以后,Combox能够显示选中,所以我们还需要增加增加一个节点选择的监听:

    public class CheckBoxTreeNodeListender extends MouseAdapter {
    
        private ZTreeCheckBox zTreeCheckBox = null;
    
        public CheckBoxTreeNodeListender(ZTreeCheckBox zTreeCheckBox) {
    
            this.zTreeCheckBox = zTreeCheckBox;
        }
    
        // 被选中事件
        @Override
        public void mousePressed(MouseEvent event) {
            
            if(event.getSource() instanceof ZTreeCheckBox){
                Point p = event.getPoint();
                int row = zTreeCheckBox.getRowForLocation(p.x, p.y);
                TreePath path = zTreeCheckBox.getPathForRow(row);
                if (path != null) {
                    CheckBoxTreeNode node = (CheckBoxTreeNode) path
                            .getLastPathComponent();
                    if (node != null) {
                        boolean isSelected = !node.isSelect();
                        node.setSelected(isSelected);
                        ((DefaultTreeModel) zTreeCheckBox.getModel()).nodeStructureChanged(node);
                    }
                }
            }
            
    //        else{
    //            String comm = ((JButton)event.getSource()).getActionCommand();
    //        }
    //        
        }
    
    }

    最后我们得到是这个样子的:

    image

    左边的按钮,表示的选择的操作:

    ① 全部的选中

    ② 全部的不选中

    ③ 选择一个子树

    ④ 去除某一个子树

    一种实现的思路,是在选择的事件分为四类,然后实现对应的逻辑,也就是对每一个节点的选择做出操作。在CheckBoxTreeNodeListender 的监听响应中添加:

    // 被选中事件
        @Override
        public void mousePressed(MouseEvent event) {
            Point p = event.getPoint();
            int row = zTreeCheckBox.getRowForLocation(p.x, p.y);
            TreePath path = zTreeCheckBox.getPathForRow(row);
            
            if(event.getSource() instanceof ZTreeCheckBox){
                if (path != null) {
                    CheckBoxTreeNode node = (CheckBoxTreeNode) path
                            .getLastPathComponent();
                    if (node != null) {
                        boolean isSelected = !node.isSelect();
                        node.setSelected(isSelected);
                        ((DefaultTreeModel) zTreeCheckBox.getModel()).nodeStructureChanged(node);
                    }
                }
            }
            
            else{
                String comm = ((JButton)event.getSource()).getActionCommand();
                if("SelectAll".equals(comm)){
                    CheckBoxTreeNode node = (CheckBoxTreeNode) path.getLastPathComponent();
                    selectAllNode(node,true);
                    ((DefaultTreeModel) zTreeCheckBox.getModel()).nodeStructureChanged(node);
                }else if("DeselectAll".equals(comm)){
                    CheckBoxTreeNode node = (CheckBoxTreeNode) path.getLastPathComponent();
                    selectAllNode(node,false);
                    ((DefaultTreeModel) zTreeCheckBox.getModel()).nodeStructureChanged(node);
                }
            }
    //        
        }
    
        private void selectAllNode(CheckBoxTreeNode node,boolean select) {
            if (node != null) {
                node.setSelected(select);
                if(node.getChildCount() > 0 ){
                    for (int i = 0; i < node.getChildCount(); i++) {
                        CheckBoxTreeNode child = (CheckBoxTreeNode) node.getChildAt(i);
                        selectAllNode(child,select);
                    }
                }
                
            }
            
        }

    类似的实现,即可满足条件,封装性不是很好,有时间在进行重构,抽成一个借口,和对应的实现。

    下一篇我们的实现成这样:

    image

    改变树节点的图片,变得好看一点。

  • 相关阅读:
    Python3抓取 深圳房地产均价数据,通过真实数据为购置不动产做决策分析(二)
    Python3抓取 深圳房地产均价数据,通过真实数据为购置不动产做决策分析(一)
    学习Make your own neural network 记录(一)
    Python3 爬取Boss直聘网 工作基本信息(数据清洗)
    Python3 爬虫爬取中国图书网(淘书团) 进阶版
    Python3 爬虫爬取中国图书网(淘书团) 记录
    修改Linux最大Socket连接限制
    linux递归删除某个文件夹
    虚拟机安装Linux小技巧
    ext/hash_map 报告过期错误和警告 deprecated or antiquated header
  • 原文地址:https://www.cnblogs.com/zhailzh/p/4074557.html
Copyright © 2011-2022 走看看