2017-07-19 24 views
3

什么我处理:如何在同一窗口中获取几棵树的所有选中框?

我工作的窗口与几个复选框树(的Java Swing)和我使用的是在计算器中,以与JCheckBox的对象JTree的代码样本。所以我做了一个CheckBoxNode类,一个CheckBoxNodeRenderer类和一个CheckBoxNodeEditor类。不过,我不明白当我在树中检查一个盒子时会发生什么。我使用了一个非常简单的“println”来查看许多函数中会发生什么,例如类CheckBoxNodeRenderer的getTreeCellRendererComponent。

我想这样做:

我有三棵树,我想获得每棵树的所有选中的元素在一个单独的元素,数组或一个ArrayList。那么,我只需读取这些数组或ArrayLists即可使用所选元素。当然,如果我取消选中一个框,则必须从数组中删除该元素。

我已经尝试过:

我不得不承认,我没有太多的想法。我试图理解当我检查一个盒子时会发生什么,并记录了许多函数,我可以观察到当我检查树中的元素时,我的日志被写入超过三次(例如getTreeCellRenderer中的日志)。

我的代码:

class CheckBoxNode extends DefaultMutableTreeNode { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1155080395876568819L; 
    private String _title; 
    private boolean _selectedStatus; 

    public CheckBoxNode(String name, boolean isSelected) { 
     this._title = name; 
     this._selectedStatus = isSelected; 
    } 

    //GETTERS 

    public String getTitle() { 
     return this._title; 
    } 

    public boolean isSelected() { 
     return this._selectedStatus; 
    } 

    //SETTERS 

    public void setTitle(String newTitle) { 
     this._title = newTitle; 
    } 

    public void setSelected(boolean isSelected) { 
     this._selectedStatus = isSelected; 
    } 

    public String toString() { 
     return _title; 
    } 
} 

CheckBoxNodeEditor

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 2616799535763664121L; 
    private CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer(); 

    //CONSTRUCTOR 

    public CheckBoxNodeEditor() {} 

    //METHODS 

    public Object getCellEditorValue() { 
     JCheckBox checkBox = renderer.getNodeRenderer(); 
     CheckBoxNode checkBoxNode = new CheckBoxNode(checkBox.getText(), checkBox.isSelected()); 
     return checkBoxNode; 
    } 

    public Component getTreeCellEditorComponent(JTree tree, Object value, 
      boolean isSelected, boolean expanded, boolean leaf, int row) { 
     Component editor = renderer.getTreeCellRendererComponent(tree, value, 
       true, expanded, leaf, row, true); 
     // editor always selected/focused 
     ItemListener itemListener = new ItemListener() { 
      public void itemStateChanged(ItemEvent itemEvent) { 
       if (stopCellEditing()) { 
        fireEditingStopped(); 
       } 
      } 
     }; 

     if (editor instanceof JCheckBox) { 
      ((JCheckBox) editor).addItemListener(itemListener); 
     } 
     return editor; 
    } 
} 

CheckBoxNodeRenderer

class CheckBoxNodeRenderer implements TreeCellRenderer { 

    private JCheckBox nodeRenderer = new JCheckBox(); 
    private Color selectionForeground, selectionBackground, textForeground, textBackground; 

    //CONSTRUCTOR 

    public CheckBoxNodeRenderer() { 
     Font fontValue; 
     fontValue = UIManager.getFont("Tree.font"); 
     if (fontValue != null) { 
      nodeRenderer.setFont(fontValue); 
     } 
     Boolean booleanValue = (Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon"); 
     nodeRenderer.setFocusPainted((booleanValue != null)&& (booleanValue.booleanValue())); 
     selectionForeground = UIManager.getColor("Tree.selectionForeground"); 
     selectionBackground = UIManager.getColor("Tree.selectionBackground"); 
     textForeground = UIManager.getColor("Tree.textForeground"); 
     textBackground = UIManager.getColor("Tree.textBackground"); 
    } 

    //METHODS 

    protected JCheckBox getNodeRenderer() { 
     return nodeRenderer; 
    } 

    public Component getTreeCellRendererComponent(JTree tree, Object value, 
      boolean selected, boolean expanded, boolean leaf, int row, 
      boolean hasFocus) { 
     Component returnValue; 
     String stringValue = tree.convertValueToText(value, selected, expanded, 
       leaf, row, false); 
     nodeRenderer.setText(stringValue); 
     nodeRenderer.setSelected(false); 
     nodeRenderer.setEnabled(tree.isEnabled()); 
     if (selected) { 
      nodeRenderer.setForeground(selectionForeground); 
      nodeRenderer.setBackground(selectionBackground); 
     } else { 
      nodeRenderer.setForeground(textForeground); 
      nodeRenderer.setBackground(textBackground); 
     } 
     if ((value != null) && (value instanceof DefaultMutableTreeNode)) { 
      Object userObject = ((DefaultMutableTreeNode) value) 
        .getUserObject(); 
      if (userObject instanceof CheckBoxNode) { 
       CheckBoxNode node = (CheckBoxNode) userObject; 
       nodeRenderer.setText(node.getTitle()); 
       nodeRenderer.setSelected(node.isSelected()); 
      } 
     } 
     returnValue = nodeRenderer; 
     return returnValue; 
    } 
} 

构建窗口和树:包括从数据库中提取数据,并建立对应的复选框树木也是如此作为包含树木和其他面板

public class WindowBuilding extends JFrame { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -634017858375515775L; 
    private Parser _parser; 

    // CONSTRUCTOR 

    public WindowBuilding() { 
     this._parser = new Parser();      //parser to extract data from the database containining all the informations 
     getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS)); //gridlayout to have all the elements in the same window 

    } 

    // METHODS 

    public void buildTrees() throws SQLException { 
     _parser.extractData(); 
     _parser.sortModels(); 
     _parser.sortCustomers(); 
     _parser.sortGroups(); 

     System.out.println(_parser.getNumberOfCustomers()); 
     System.out.println(_parser.getNumberOfGroups()); 

     // Families, Types and Models arrays 
     CheckBoxNode[] myFamilies = new CheckBoxNode[_parser.getNumberOfFamilies()]; 
     CheckBoxNode[] myTypes = new CheckBoxNode[_parser.getNumberOfTypes()]; 
     CheckBoxNode[] myModels = new CheckBoxNode[_parser.getNumberOfModels()]; 

     // Root 
     CheckBoxNode root = new CheckBoxNode("All", false); 

     // Complete the arrays 
     for (int i = 0; i < _parser.getNumberOfFamilies(); i++) { 
      myFamilies[i] = new CheckBoxNode(_parser.getFamily(i), false); 
     } 
     for (int i = 0; i < _parser.getNumberOfTypes(); i++) { 
      myTypes[i] = new CheckBoxNode(_parser.getType(i), false); 
     } 
     for (int i = 0; i < _parser.getNumberOfModels(); i++) { 
      myModels[i] = new CheckBoxNode(_parser.getModel(i), false); 
     } 

     // Add Models to Types 
     for (int i = 0; i < myModels.length; i++) { 
      if (myModels[i].toString().startsWith("T119")) { 
       myTypes[1].add(myModels[i]); 
      } 
      if (myModels[i].toString().startsWith("T120")) { 
       myTypes[2].add(myModels[i]); 
      } 
      if (myModels[i].toString().startsWith("T121")) { 
       myTypes[3].add(myModels[i]); 
      } 
      if (myModels[i].toString().startsWith("T130")) { 
       myTypes[4].add(myModels[i]); 
      } 
      if (myModels[i].toString().startsWith("T150")) { 
       myTypes[7].add(myModels[i]); 
      } 
     } 

     // Add Types to Families 
     for (int i = 0; i < myTypes.length; i++) { 
      if (myTypes[i].toString().startsWith("T119") || myTypes[i].toString().startsWith("T12")) { 
       myFamilies[0].add(myTypes[i]); 
      } 
      if (myTypes[i].toString().startsWith("T13")) { 
       myFamilies[1].add(myTypes[i]); 
      } 
      if (myTypes[i].toString().startsWith("T15")) { 
       myFamilies[3].add(myTypes[i]); 
      } 
     } 

     // Add Families to Root 
     for (int i = 0; i < _parser.getNumberOfFamilies(); i++) { 
      if (i != 2) { 
       root.add(myFamilies[i]); 
      } 
     } 

     // Customers and Groups arrays 
     CheckBoxNode[] myCustomers = new CheckBoxNode[_parser.getNumberOfCompanies()]; 
     CheckBoxNode[] myGroups = new CheckBoxNode[_parser.getNumberOfFleets()]; 

     // Root for Groups 
     CheckBoxNode rootGroups = new CheckBoxNode("All", false); 

     // Complete the arrays 
     for (int i = 0; i < _parser.getNumberOfCustomers(); i++) { 
      myCustomers[i] = new CheckBoxNode(_parser.getCustomer(i), false); 
     } 
     for (int i = 0; i < _parser.getNumberOfGroups(); i++) { 
      myGroups[i] = new CheckBoxNode(_parser.getGroup(i), false); 
     } 

     // Add Groups to Customers 
     for (int i = 0; i < myCustomers.length; i++) { 
      for (int j = 0; j < Groups.length; j++) { 
       if (myFleets[j].getTitle() 
         .startsWith(myCustomers[i].getTitle())) { 
        myCustomers[i].add(myGroups[j]); 
       } 
      } 
     } 

     // Add Companies to Root 
     for (int i = 0; i < myCustomers.length; i++) { 
      rootGroups.add(myCustomers[i]); 
     } 

     // Test Types array 
     CheckBoxNode[] myTests = new CheckBoxNode[8]; 

     // Root 
     CheckBoxNode rootTests = new CheckBoxNode("All", false); 

     // Complete the arrays 
     myTests[0] = new CheckBoxNode("FIRST TEST", false); 
     myTests[1] = new CheckBoxNode("SECOND TEST", false); 
     myTests[2] = new CheckBoxNode("CHECK TEST", false); 
     myTests[3] = new CheckBoxNode("RUN TEST", false); 
     myTests[4] = new CheckBoxNode("STATIC", false); 
     myTests[5] = new CheckBoxNode("TYPICAL TEST", false); 
     myTests[6] = new CheckBoxNode("SIMU VALIDATION", false); 
     myTests[7] = new CheckBoxNode("OTHER", false); 

     // Add Test Types to root 
     for(int i=0; i<8; i++) { 
      rootTests.add(myTests[i]); 
     } 

     // TPP Array 
     CheckBoxNode[] myTpp = new CheckBoxNode[30]; 

     // Root 
     CheckBoxNode rootTpp = new CheckBoxNode("All", false); 

     // Complete the arrays 
     for(int i=0; i<30; i++) { 
      myTpp[i] = new CheckBoxNode("TPP "+(i+1), false); 
     } 

     // Add Tpp to root 
     for(int i=0; i<myTpp.length; i++) { 
      rootTpp.add(myTpp[i]); 
     } 


     // Create objects JTree 
     JTree treeProducts = new JTree(root); 
     JTree treeGroups = new JTree(rootGroups); 
     JTree treeTests = new JTree(rootTests); 
     JTree treeTpp = new JTree(rootTpp); 

     // Trees renderer 
     CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer(); 

     // Products tree parameters 
     treeProducts.setCellRenderer(renderer); 
     treeProducts.setCellEditor(new CheckBoxNodeEditor()); 
     treeProducts.setEditable(true); 

     // Groups tree parameters 
     treeGroups.setCellRenderer(renderer); 
     treeGroups.setCellEditor(new CheckBoxNodeEditor()); 
     treeGroups.setEditable(true); 

     // Test Types tree parameters 
     treeTests.setCellRenderer(renderer); 
     treeTests.setCellEditor(new CheckBoxNodeEditor()); 
     treeTests.setEditable(true); 

     // Tpp tree parameters 
     treeTpp.setCellRenderer(renderer); 
     treeTpp.setCellEditor(new CheckBoxNodeEditor()); 
     treeTpp.setEditable(true); 

     // Building panels 
     JPanel mainPanel = new JPanel(); 
     JPanel titlePanel = new JPanel(); 
     JPanel dataPropPanel = new JPanel(); 
     JPanel topPanel = new JPanel(); 
     JPanel bottomPanel = new JPanel(); 
     JPanel spinnersPanel = new JPanel(); 
     JPanel msnPanel = new JPanel(); 
     JPanel datePanel = new JPanel(); 
     JPanel selectTppPanel = new JPanel(); 
     JPanel tppPanel = new JPanel(); 
     JPanel descPanel = new JPanel(); 
     JPanel labelsPanel= new JPanel(); 
     JPanel fieldsPanel = new JPanel(); 
     mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); 
     spinnersPanel.setLayout(new BoxLayout(spinnersPanel, BoxLayout.Y_AXIS)); 
     labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); 
     fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS)); 
     descPanel.setLayout(new BoxLayout(descPanel, BoxLayout.Y_AXIS)); 
     topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS)); 
     bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS)); 
     tppPanel.setLayout(new BoxLayout(tppPanel, BoxLayout.X_AXIS)); 
     msnPanel.setLayout(new BoxLayout(msnPanel, BoxLayout.X_AXIS)); 
     datePanel.setLayout(new BoxLayout(datePanel, BoxLayout.X_AXIS)); 
     titlePanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 
     dataPropPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 
     selectTppPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 

     // Dimensions 
     Dimension dimLabel = new Dimension(300,35); 

     // JScrollPane for trees 
     JScrollPane prodPane = new JScrollPane(treeProducts);   // ScrollPane products 
     prodPane.setMaximumSize(new Dimension(250,300)); 
     JScrollPane groupPane = new JScrollPane(treeGroups);   // ScrollPane groups 
     groupPpane.setMaximumSize(new Dimension(250,300)); 
     JScrollPane tePane = new JScrollPane(treeTests); 
     tePane.setMaximumSize(new Dimension(250,300)); 
     JScrollPane tppPane = new JScrollPane(treeTpp); 
     tppPane.setMaximumSize(new Dimension(600,300)); 

     // Labels for main panel 
     JLabel title = new JLabel("Generate Test Points"); 
     titlePanel.add(title); 
     JLabel topLabel = new JLabel("Data properties"); 
     dataPropPanel.add(topLabel); 
     JLabel bottomLabel = new JLabel("Select TPP"); 
     selectTppPanel.add(bottomLabel); 

     // MSN Panel 
     SpinnerModel model1 = new SpinnerNumberModel(0,0,10000,1); 
     SpinnerModel model2 = new SpinnerNumberModel(0,0,10000,1); 
     JSpinner spinner1 = new JSpinner(model1); 
     JSpinner spinner2 = new JSpinner(model2); 
     msnPanel.add(spinner1); 
     msnPanel.add(new JLabel(" to ")); 
     msnPanel.add(spinner2); 
     msnPanel.setMaximumSize(dimLabel); 

     // Date Panel 
     SpinnerModel date1 = new SpinnerDateModel(); 
     SpinnerModel date2 = new SpinnerDateModel(); 
     JSpinner dateSpinner1 = new JSpinner(date1); 
     JSpinner dateSpinner2 = new JSpinner(date2); 
     datePanel.add(dateSpinner1); 
     datePanel.add(new JLabel(" to ")); 
     datePanel.add(dateSpinner2); 
     datePanel.setMaximumSize(dimLabel); 

     // Spinners Panel 
     JLabel msnRangeLabel = new JLabel("MSN Range"); 
     spinnersPanel.add(msnRangeLabel); 
     spinnersPanel.add(msnPanel); 
     spinnersPanel.add(new JLabel("Test Date Range")); 
     spinnersPanel.add(datePanel); 

     // Top Panel 
     JLabel acPropertiesLabel = new JLabel("Product properties"); 
     topPanel.add(prodPropertiesLabel); 
     topPanel.add(prodPane); 
     topPanel.add(new JLabel("Groups")); 
     topPanel.add(groupPane); 
     topPanel.add(new JLabel("Test properties")); 
     topPanel.add(tePane); 
     topPanel.add(spinnersPanel); 

     // Labels Panel 
     JLabel tppName = new JLabel("TPP Name"); 
     tppName.setMaximumSize(new Dimension(100,35)); 
     labelsPanel.add(tppName); 
     labelsPanel.add(new JLabel("TPP List")); 

     // Fields Panel 
     JTextField textField = new JTextField(); 
     textField.setMaximumSize(new Dimension(600,35)); 
     fieldsPanel.add(textField); 
     fieldsPanel.add(tppane); 

     // TPP Panel 
     tppPanel.add(labelsPanel); 
     tppPanel.add(fieldsPanel); 

     // Desc Panel 
     descPanel.add(new JLabel("label for description")); 
     descPanel.add(new JLabel("label for description")); 
     descPanel.add(new JLabel("label for description")); 
     descPanel.add(new JLabel("label for description")); 
     descPanel.add(new JLabel("label for description")); 

     // Bottom Panel 
     bottomPanel.add(tppPanel); 
     bottomPanel.add(descPanel); 

     // Main Panel 
     mainPanel.add(titlePanel); 
     mainPanel.add(dataPropPanel); 
     mainPanel.add(topPanel); 
     mainPanel.add(selectTppPanel); 
     mainPanel.add(bottomPanel); 
     this.getContentPane().add(mainPanel); 

     // Window parameters 
     ((JComponent) this.getContentPane()).setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); //add a border to the window 
     this.setSize(1600,900); 
     this.setTitle("Generate Test Points"); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setVisible(true); 

    } 
} 

主要类应用程序的主窗口

public class TestPointGeneration { 

    /** 
    * @param args 
    * @throws ParserConfigurationException 
    * @throws SAXException 
    * @throws IOException 
    * @throws SQLException 
    */ 
    public static void main(String[] args) throws SQLException { 
     WindowBuilding window = new WindowBuilding(); 
     window.buildTrees(); 
     window.setVisible(true); 

    } 
} 

让我知道,如果你需要我的代码的详细信息,我非常感谢大家。

+0

您正在使用哪个IDE?设置断点可以提供比记录更多的信息。 –

+0

我正在使用Eclipse。是的你是对的,但我无法在这里获得更多有关断点的信息。 – LaPalme

+0

你可以发布你的主课吗? – sirandy

回答

1

我改编自这个答案的解决方案: How to get all the checked boxes of several trees in a same window?

我觉得你的类CheckBoxNode缺少的功能,主要是状态的回购信息,但随后在CheckBoxNodeEditor类,你刚刚加入JCheckBox的,在我认为它必须是一个数组或列表,并且checkBoxNode必须处理事件以检查它们是否被选中或未选中。

主类:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.tree.TreePath; 

public class Main extends JFrame { 

    private static final long serialVersionUID = 4648172894076113183L; 

    public Main() { 
     super(); 
     setSize(500, 500); 
     this.getContentPane().setLayout(new BorderLayout()); 
     final JCheckBoxTree cbt = new JCheckBoxTree(); 
     final JButton button = new JButton("get checked"); 
     JPanel panel = new JPanel(); 
     panel.add(cbt); 
     panel.add(button); 
     this.getContentPane().add(panel); 

     button.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       printChecked(cbt); 
      } 
     }); 

     cbt.addCheckChangeEventListener(new JCheckBoxTree.CheckChangeEventListener() { 
      public void checkStateChanged(JCheckBoxTree.CheckChangeEvent event) { 
       printChecked(cbt); 
      } 
     });   
     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    } 

    public void printChecked(final JCheckBoxTree cbt) { 
     System.out.println("Select items"); 
     TreePath[] paths = cbt.getCheckedPaths(); 
     for (TreePath tp : paths) { 
      for (Object pathPart : tp.getPath()) { 
       System.out.print(pathPart + ","); 
      }     
      System.out.println(); 
     } 
    } 

    public static void main(String args[]) { 
     Main m = new Main(); 
     m.setVisible(true); 
    } 
} 

JTree类的

package com.stackoverflow.checkedboxes; 
import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.EventListener; 
import java.util.EventObject; 
import java.util.HashMap; 
import java.util.HashSet; 

import javax.swing.JCheckBox; 
import javax.swing.JPanel; 
import javax.swing.JTree; 
import javax.swing.event.EventListenerList; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeSelectionModel; 
import javax.swing.tree.TreeCellRenderer; 
import javax.swing.tree.TreeModel; 
import javax.swing.tree.TreeNode; 
import javax.swing.tree.TreePath; 

public class JCheckBoxTree extends JTree { 

    private static final long serialVersionUID = -4194122328392241790L; 

    JCheckBoxTree selfPointer = this; 



    // Defining data structure that will enable to fast check-indicate the state of each node 
    // It totally replaces the "selection" mechanism of the JTree 
    private class CheckedNode { 
     boolean isSelected; 
     boolean hasChildren; 
     boolean allChildrenSelected; 

     public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) { 
      isSelected = isSelected_; 
      hasChildren = hasChildren_; 
      allChildrenSelected = allChildrenSelected_; 
     } 
    } 
    HashMap<TreePath, CheckedNode> nodesCheckingState; 
    HashSet<TreePath> checkedPaths = new HashSet<TreePath>(); 

    // Defining a new event type for the checking mechanism and preparing event-handling mechanism 
    protected EventListenerList listenerList = new EventListenerList(); 

    public class CheckChangeEvent extends EventObject {  
     private static final long serialVersionUID = -8100230309044193368L; 

     public CheckChangeEvent(Object source) { 
      super(source);   
     }  
    } 

    public interface CheckChangeEventListener extends EventListener { 
     public void checkStateChanged(CheckChangeEvent event); 
    } 

    public void addCheckChangeEventListener(CheckChangeEventListener listener) { 
     listenerList.add(CheckChangeEventListener.class, listener); 
    } 
    public void removeCheckChangeEventListener(CheckChangeEventListener listener) { 
     listenerList.remove(CheckChangeEventListener.class, listener); 
    } 

    void fireCheckChangeEvent(CheckChangeEvent evt) { 
     Object[] listeners = listenerList.getListenerList(); 
     for (int i = 0; i < listeners.length; i++) { 
      if (listeners[i] == CheckChangeEventListener.class) { 
       ((CheckChangeEventListener) listeners[i + 1]).checkStateChanged(evt); 
      } 
     } 
    } 

    // Override 
    public void setModel(TreeModel newModel) { 
     super.setModel(newModel); 
     resetCheckingState(); 
    } 

    // New method that returns only the checked paths (totally ignores original "selection" mechanism) 
    public TreePath[] getCheckedPaths() { 
     return checkedPaths.toArray(new TreePath[checkedPaths.size()]); 
    } 

    // Returns true in case that the node is selected, has children but not all of them are selected 
    public boolean isSelectedPartially(TreePath path) { 
     CheckedNode cn = nodesCheckingState.get(path); 
     return cn.isSelected && cn.hasChildren && !cn.allChildrenSelected; 
    } 

    private void resetCheckingState() { 
     nodesCheckingState = new HashMap<TreePath, CheckedNode>(); 
     checkedPaths = new HashSet<TreePath>(); 
     DefaultMutableTreeNode node = (DefaultMutableTreeNode)getModel().getRoot(); 
     if (node == null) { 
      return; 
     } 
     addSubtreeToCheckingStateTracking(node); 
    } 

    // Creating data structure of the current model for the checking mechanism 
    private void addSubtreeToCheckingStateTracking(DefaultMutableTreeNode node) { 
     TreeNode[] path = node.getPath(); 
     TreePath tp = new TreePath(path); 
     CheckedNode cn = new CheckedNode(false, node.getChildCount() > 0, false); 
     nodesCheckingState.put(tp, cn); 
     for (int i = 0 ; i < node.getChildCount() ; i++) {    
      addSubtreeToCheckingStateTracking((DefaultMutableTreeNode) tp.pathByAddingChild(node.getChildAt(i)).getLastPathComponent()); 
     } 
    } 

    // Overriding cell renderer by a class that ignores the original "selection" mechanism 
    // It decides how to show the nodes due to the checking-mechanism 
    private class CheckBoxCellRenderer extends JPanel implements TreeCellRenderer {  
     private static final long serialVersionUID = -7341833835878991719L;  
     JCheckBox checkBox;  
     public CheckBoxCellRenderer() { 
      super(); 
      this.setLayout(new BorderLayout()); 
      checkBox = new JCheckBox(); 
      add(checkBox, BorderLayout.CENTER); 
      setOpaque(false); 
     } 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, 
       boolean selected, boolean expanded, boolean leaf, int row, 
       boolean hasFocus) { 
      DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 
      Object obj = node.getUserObject();   
      TreePath tp = new TreePath(node.getPath()); 
      CheckedNode cn = nodesCheckingState.get(tp); 
      if (cn == null) { 
       return this; 
      } 
      checkBox.setSelected(cn.isSelected); 
      checkBox.setText(obj.toString()); 
      checkBox.setOpaque(cn.isSelected && cn.hasChildren && ! cn.allChildrenSelected); 
      return this; 
     }  
    } 

    public JCheckBoxTree() { 
     super(); 
     // Disabling toggling by double-click 
     this.setToggleClickCount(0); 
     // Overriding cell renderer by new one defined above 
     CheckBoxCellRenderer cellRenderer = new CheckBoxCellRenderer(); 
     this.setCellRenderer(cellRenderer); 

     // Overriding selection model by an empty one 
     DefaultTreeSelectionModel dtsm = new DefaultTreeSelectionModel() {  
      private static final long serialVersionUID = -8190634240451667286L; 
      // Totally disabling the selection mechanism 
      public void setSelectionPath(TreePath path) { 
      }   
      public void addSelectionPath(TreePath path) {      
      }   
      public void removeSelectionPath(TreePath path) { 
      } 
      public void setSelectionPaths(TreePath[] pPaths) { 
      } 
     }; 
     // Calling checking mechanism on mouse click 
     this.addMouseListener(new MouseListener() { 
      public void mouseClicked(MouseEvent arg0) { 
       TreePath tp = selfPointer.getPathForLocation(arg0.getX(), arg0.getY()); 
       if (tp == null) { 
        return; 
       } 
       boolean checkMode = ! nodesCheckingState.get(tp).isSelected; 
       checkSubTree(tp, checkMode); 
       updatePredecessorsWithCheckMode(tp, checkMode); 
       // Firing the check change event 
       fireCheckChangeEvent(new CheckChangeEvent(new Object())); 
       // Repainting tree after the data structures were updated 
       selfPointer.repaint();       
      }   
      public void mouseEntered(MouseEvent arg0) {   
      }   
      public void mouseExited(MouseEvent arg0) {    
      } 
      public void mousePressed(MouseEvent arg0) {    
      } 
      public void mouseReleased(MouseEvent arg0) { 
      }   
     }); 
     this.setSelectionModel(dtsm); 
    } 

    // When a node is checked/unchecked, updating the states of the predecessors 
    protected void updatePredecessorsWithCheckMode(TreePath tp, boolean check) { 
     TreePath parentPath = tp.getParentPath(); 
     // If it is the root, stop the recursive calls and return 
     if (parentPath == null) { 
      return; 
     }  
     CheckedNode parentCheckedNode = nodesCheckingState.get(parentPath); 
     DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) parentPath.getLastPathComponent();  
     parentCheckedNode.allChildrenSelected = true; 
     parentCheckedNode.isSelected = false; 
     for (int i = 0 ; i < parentNode.getChildCount() ; i++) {     
      TreePath childPath = parentPath.pathByAddingChild(parentNode.getChildAt(i)); 
      CheckedNode childCheckedNode = nodesCheckingState.get(childPath);   
      // It is enough that even one subtree is not fully selected 
      // to determine that the parent is not fully selected 
      if (! childCheckedNode.allChildrenSelected) { 
       parentCheckedNode.allChildrenSelected = false;  
      } 
      // If at least one child is selected, selecting also the parent 
      if (childCheckedNode.isSelected) { 
       parentCheckedNode.isSelected = true; 
      } 
     } 
     if (parentCheckedNode.isSelected) { 
      checkedPaths.add(parentPath); 
     } else { 
      checkedPaths.remove(parentPath); 
     } 
     // Go to upper predecessor 
     updatePredecessorsWithCheckMode(parentPath, check); 
    } 

    // Recursively checks/unchecks a subtree 
    protected void checkSubTree(TreePath tp, boolean check) { 
     CheckedNode cn = nodesCheckingState.get(tp); 
     cn.isSelected = check; 
     DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp.getLastPathComponent(); 
     for (int i = 0 ; i < node.getChildCount() ; i++) {    
      checkSubTree(tp.pathByAddingChild(node.getChildAt(i)), check); 
     } 
     cn.allChildrenSelected = check; 
     if (check) { 
      checkedPaths.add(tp); 
     } else { 
      checkedPaths.remove(tp); 
     } 
    } 

} 

enter image description here 输出: 选择项目 JTree的,颜色,蓝色, JTree的,颜色,红色, JTree的,颜色, JTree的,颜色,黄色, JTree的,

+1

谢谢sirandy。我也分享我写的解决方案。好处是我只能得到被选框的名字。尽管如此,使用您的解决方案,当我检查颜色时,检查复选框的所有子项会更容易。 '公共对象getCellEditorValue(){ \t \t JCheckBox的复选框= renderer.getNodeRenderer(); \t \t CheckBoxNode checkBoxNode =新CheckBoxNode(checkBox.getText(),checkBox.isSelected()); (checkBox.isSelected()){ \t \t if(checkBox.isSelected()){ \t \t \t window.addSelectedElement(checkBox.getText()); \t \t} else { \t \t \t window.removeUnselectedElement(checkBox.getText()); \t \t} \t \t回报checkBoxNode; \t}' – LaPalme

相关问题