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

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

你可能感兴趣的:(JTree)