How to get all marked fields of multiple trees in one window?

What I mean:

I am working on a window with multiple Checkboxes (Java Swing) and I used the sample codes I found on stackoverflow to create a JTree with JCheckBox objects. So I created a CheckBoxNode class, a CheckBoxNodeRenderer class and a CheckBoxNodeEditor class. However, I don't understand what actually happens when I check the box on the tree. I used a very simple "println" to see what is going on in many functions, such as the getTreeCellRendererComponent of the CheckBoxNodeRenderer class.

What I would like to do:

I have three trees and I would like to get all checked elements of each tree in a separate element, array or ArrayList. So, I can work with the selected items just by looking at those Arrays or ArrayLists. Of course, if I uncheck the box, the item has to be removed from the array.

What I've already tried:

I have to admit that I didn't have many ideas. I tried to understand what happens when I check the logs field in many functions, and I could notice that when I check the item in the tree, my logs are written more than three times (for example, the getTreeCellRenderer log).

My code:

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;
    }
}

      

Building window and trees: This consists of extracting data from the database and creating checkbox trees, as well as in the main application window containing trees and other panels.

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);

    }
}

      

Main class

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);

    }
}

      

Let me know if you need more information on my code and I am very grateful to all of you.

+3


source to share


1 answer


I adapted the solution from this answer: How to get all the marked fields of multiple trees in one window?

I think your CheckBoxNode class is missing functionality, basically it is repo information for status, but then in your CheckBoxNodeEditor class you only add JCheckBox, in my opinion it should be an array or list and checkBoxNode should handle events to check if they are marked or not marked.

Main class:

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 class

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 Conclusion: Select Products JTree, Color, Blue, JTree, Colors, Red, JTree, Colors, JTree, Colors, Yellow, JTree,

+1


source







All Articles