Swing树结构节点渲染JCheckbox

来源:互联网 发布:java里定义全局变量 编辑:程序博客网 时间:2024/05/07 17:55

package tip;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;

import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

public class MyTreeWithCheckbox{
 private HashMap<TreeNode, TristateCheckBox.State> hm = new HashMap<TreeNode, TristateCheckBox.State>();
   public MyTreeWithCheckbox(JTree jTree) {
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) jTree.getModel().getRoot();
          for (Enumeration<?> em = root.depthFirstEnumeration(); em.hasMoreElements(); ) {
           DefaultMutableTreeNode node = (DefaultMutableTreeNode) em.nextElement();
              hm.put(node, TristateCheckBox.NOT_SELECTED);
          }
          jTree.setCellRenderer(new MyTreeWithCheckboxRenderer());
          jTree.addMouseListener(new MyTreeWithCheckboxSelectionListener());
      }
    
      /**
       *
       * 返回所有选中的路径
       */
      public TreePath[] getSelectionPaths() {
          Iterator<TreeNode> it = hm.keySet().iterator();
          ArrayList<TreePath> al = new ArrayList<TreePath>();
          while (it.hasNext()) {
              DefaultMutableTreeNode o = (DefaultMutableTreeNode) it.next();
              if (o.isLeaf() && ((TristateCheckBox.State) hm.get(o)).equals(TristateCheckBox.SELECTED)) {
                  al.add(new TreePath(o.getPath()));
              }
          }
          return (TreePath[]) al.toArray(new TreePath[0]);
      }
      /**
       * 给树结构添加监听
       *
       */
      class MyTreeWithCheckboxSelectionListener implements MouseListener {
       int i = 0;
          public void valueChanged(TreeSelectionEvent e) {
              JTree jTree = (JTree) (e.getSource());
              DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
              if (node == null) {
                  return;
              }
              // 修改当前节点的状态
              if (((TristateCheckBox.State) hm.get(node)).equals(TristateCheckBox.SELECTED)) {
                  hm.put(node, TristateCheckBox.NOT_SELECTED);
              } else {
                  hm.put(node, TristateCheckBox.SELECTED);
              }
              updateAllParentNodes(node);
              updateAllChildNodes(node);
              jTree.setSelectionPath(null);
              jTree.repaint();
          }
          /**
           * 树节点添加点击处理事件
           * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
           */
          @Override
    public void mouseClicked(MouseEvent mouseevent)
    {
           int i = 0;
           Iterator<TreeNode> num =hm.keySet().iterator();
           while(num.hasNext()){
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) num.next();
            ParamViewUserObject obj = (ParamViewUserObject)node.getUserObject();
            if(obj.isMo()&&obj.isSelected()){
             i++;
            }
           }
           JTree jTree = (JTree) (mouseevent.getSource());
              DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
              if (node == null) {
                  return;
              }
              ParamViewUserObject obj = (ParamViewUserObject)node.getUserObject();
              if(node.isLeaf()||obj.isMo()){
               // 修改当前节点的状态
               if (((TristateCheckBox.State) hm.get(node)).equals(TristateCheckBox.SELECTED)) {
                obj.setSelected(false);
                   hm.put(node, TristateCheckBox.NOT_SELECTED);
               } else {
                if(i<5){
                 obj.setSelected(true);
                    hm.put(node, TristateCheckBox.SELECTED);
                }else{
                 //null代表的适用于展示在哪里
                 JOptionPane.showMessageDialog(null, "处于性能考虑,目前最多可选5个MO级别参数");
                }
               }
               updateAllParentNodes(node);
               updateAllChildNodes(node);
               jTree.setSelectionPath(null);
               jTree.repaint();
              }
    }
        
          /**
           * 用递归方法修改从当前节点到根节点的所有节点的状态
           * @param node
           */
          public void updateAllParentNodes(DefaultMutableTreeNode node) {
           int i = 0;
              TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
              if (node.isRoot()) {
                  return;
              }
              if(status.equals(TristateCheckBox.SELECTED)){
               ((ParamViewUserObject)(((DefaultMutableTreeNode)(node.getParent())).getUserObject())).setSelected(true);
               hm.put(node.getParent(), TristateCheckBox.SELECTED);
                 }else{
                  for (Enumeration<?> em = node.getParent().children(); em.hasMoreElements(); ) {
                   DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
                   if (!(((TristateCheckBox.State) hm.get(tn)).equals(status))) {
                    hm.put(node.getParent(), TristateCheckBox.SELECTED);
                    break;
                   }
                   i++;
                  }
                 }
              if(i == node.getParent().getChildCount()){
                  ((ParamViewUserObject)(((DefaultMutableTreeNode)(node.getParent())).getUserObject())).setSelected(false);
               hm.put(node.getParent(), status);
              }
              updateAllParentNodes((DefaultMutableTreeNode) node.getParent());
          }
        
          /**
           * 用递归方法修改以当前节点为根的子树的所有节点的状态
           *
           * @param node
           */
          public void updateAllChildNodes(DefaultMutableTreeNode node) {
              TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
              for (Enumeration<?> em = node.depthFirstEnumeration(); em.hasMoreElements(); ) {
                  DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
                  if(status.equals(TristateCheckBox.SELECTED)){
                   ((ParamViewUserObject)tn.getUserObject()).setSelected(true);
                  }else{
                   ((ParamViewUserObject)tn.getUserObject()).setSelected(false);
                  }
                  hm.put(tn, status);
              }
          }
    @Override
    public void mouseEntered(MouseEvent mouseevent)
    {
    }

    @Override
    public void mouseExited(MouseEvent mouseevent)
    {
    }

    @Override
    public void mousePressed(MouseEvent mouseevent)
    {
    }

    @Override
    public void mouseReleased(MouseEvent mouseevent)
    {
    }
      }
  /**
   * 给mo以及leaf节点渲染checkbox的类
   *
   */
  class MyTreeWithCheckboxRenderer extends DefaultTreeCellRenderer {
    private static final long serialVersionUID = 1L;
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
                  boolean expanded, boolean leaf, int row, boolean hasFocus) {
     ParamViewUserObject obj = (ParamViewUserObject)((DefaultMutableTreeNode)value).getUserObject();
       DefaultTreeCellRenderer nonLeaf = new DefaultTreeCellRenderer();
       if(leaf||obj.isMo()){
        TristateCheckBox checkBox = new TristateCheckBox(value.toString());
               checkBox.setOpaque(false);
               DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
               checkBox.setState(((TristateCheckBox.State) hm.get(node)));
               return checkBox;
       }else{
        return nonLeaf.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
       }
          }
      }
}

三态树类

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ActionMapUIResource;

public class TristateCheckBox extends JCheckBox {
    /**
  *
  */
 private static final long serialVersionUID = 1L;
 /** This is a type-safe enumerated type */
    public static class State {
        private State() {}
    }

    public static final State NOT_SELECTED = new State();
    public static final State SELECTED = new State();
    public static final State DONT_CARE = new State();
    private final TristateDecorator model;
    public TristateCheckBox(String text, Icon icon, State initial) {
        super(text, icon);
        // Add a listener for when the mouse is pressed
        super.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                grabFocus();
                model.nextState();
            }
        });
        // Reset the keyboard action map
        ActionMap map = new ActionMapUIResource();
        map.put("pressed", new AbstractAction() {
            /**
    *
    */
   private static final long serialVersionUID = 1L;

   public void actionPerformed(ActionEvent e) {
                grabFocus();
                model.nextState();
            }
        });
        map.put("released", null);
        SwingUtilities.replaceUIActionMap(this, map);
        // set the model to the adapted model
        model = new TristateDecorator(getModel());
        setModel(model);
        setState(initial);
    }
    public TristateCheckBox(String text, State initial) {
        this(text, null, initial);
    }
    public TristateCheckBox(String text) {
        this(text, DONT_CARE);
    }
    public TristateCheckBox() {
        this(null);
    }
    /** No one may add mouse listeners, not even Swing! */
    public void addMouseListener(MouseListener l) {}
    /**
     * Set the new state to either SELECTED, NOT_SELECTED or
     * DONT_CARE.  If state == null, it is treated as DONT_CARE.
     */
    public void setState(State state) {
        model.setState(state);
    }
    /** Return the current state, which is determined by the
     * selection status of the model. */
    public State getState() {
        return model.getState();
    }
    public void setSelected(boolean b) {
        if (b) {
            setState(SELECTED);
        } else {
            setState(NOT_SELECTED);
        }
    }
    /**
     * Exactly which Design Pattern is this?  Is it an Adapter,
     * a Proxy or a Decorator?  In this case, my vote lies with the
     * Decorator, because we are extending functionality and
     * "decorating" the original model with a more powerful model.
     */
    private class TristateDecorator implements ButtonModel {
        private final ButtonModel other;
        private TristateDecorator(ButtonModel other) {
            this.other = other;
        }
        private void setState(State state) {
            if (state == NOT_SELECTED) {
                other.setArmed(false);
                setPressed(false);
                setSelected(false);
            } else if (state == SELECTED) {
                other.setArmed(false);
                setPressed(false);
                setSelected(true);
            } else { // either "null" or DONT_CARE
                other.setArmed(true);
                setPressed(true);
                setSelected(true);
            }
        }
        /**
         * The current state is embedded in the selection / armed
         * state of the model.
         *
         * We return the SELECTED state when the checkbox is selected
         * but not armed, DONT_CARE state when the checkbox is
         * selected and armed (grey) and NOT_SELECTED when the
         * checkbox is deselected.
         */
        private State getState() {
            if (isSelected() && !isArmed()) {
                // normal black tick
                return SELECTED;
            } else if (isSelected() && isArmed()) {
                // don't care grey tick
                return DONT_CARE;
            } else {
                // normal deselected
                return NOT_SELECTED;
            }
        }
        /** We rotate between NOT_SELECTED, SELECTED and DONT_CARE.*/
        private void nextState() {
            State current = getState();
            if (current == NOT_SELECTED) {
                setState(SELECTED);
            } else if (current == SELECTED) {
                setState(DONT_CARE);
            } else if (current == DONT_CARE) {
                setState(NOT_SELECTED);
            }
        }
        /** Filter: No one may change the armed status except us. */
        public void setArmed(boolean b) {
        }
        /** We disable focusing on the component when it is not
         * enabled. */
        public void setEnabled(boolean b) {
            setFocusable(b);
            other.setEnabled(b);
        }
        /** All these methods simply delegate to the "other" model
         * that is being decorated. */
        public boolean isArmed() {
            return other.isArmed();
        }
        public boolean isSelected() {
            return other.isSelected();
        }
        public boolean isEnabled() {
            return other.isEnabled();
        }
        public boolean isPressed() {
            return other.isPressed();
        }
        public boolean isRollover() {
            return other.isRollover();
        }
        public void setSelected(boolean b) {
            other.setSelected(b);
        }
        public void setPressed(boolean b) {
            other.setPressed(b);
        }
        public void setRollover(boolean b) {
            other.setRollover(b);
        }
        public void setMnemonic(int key) {
            other.setMnemonic(key);
        }
        public int getMnemonic() {
            return other.getMnemonic();
        }
        public void setActionCommand(String s) {
            other.setActionCommand(s);
        }
        public String getActionCommand() {
            return other.getActionCommand();
        }
        public void setGroup(ButtonGroup group) {
            other.setGroup(group);
        }
        public void addActionListener(ActionListener l) {
            other.addActionListener(l);
        }
        public void removeActionListener(ActionListener l) {
            other.removeActionListener(l);
        }
        public void addItemListener(ItemListener l) {
            other.addItemListener(l);
        }
        public void removeItemListener(ItemListener l) {
            other.removeItemListener(l);
        }
        public void addChangeListener(ChangeListener l) {
            other.addChangeListener(l);
        }
        public void removeChangeListener(ChangeListener l) {
            other.removeChangeListener(l);
        }
        public Object[] getSelectedObjects() {
            return other.getSelectedObjects();
        }
    }
}

0 0
原创粉丝点击