如何在同一个窗口中获取多个树的所有复选框?

我正在处理的是:

我在一个带有几个Checkboxes Trees(Java Swing)的窗口上工作,我使用了stackoverflow中的代码示例来创建一个带有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);

    }
}

如果您需要有关我的代码的更多信息,请告诉我,我非常感谢你们所有人.

最佳答案 我从这个答案改编了解决方案:

How to get all the checked boxes of several trees in a same window?

我认为你的类CheckBoxNode缺少功能,基本上是状态的repo信息,但是在你的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);
        }
    }

}

《如何在同一个窗口中获取多个树的所有复选框?》
输出:
    选择项目
    JTree的,颜色,蓝色,
    JTree的,颜色,红色,
    JTree的,颜色,
    JTree的,颜色,黄色,
    JTree的,

点赞