Results 1 to 6 of 6
  1. #1
    lisichka's Avatar
    lisichka is offline Member
    Join Date
    Feb 2012
    Location
    Greece
    Posts
    5
    Rep Power
    0

    Default Automatically select parent node(s) of a leaf in a JTree with checkboxes

    Hello.

    I have implemented a JTree with a CellRenderer with JCheckBoxes.

    Upon selection of a leaf checkbox, how can I get selected all its ancestors (its parent, the parent of the parent, ...., the root) ?
    I am trying to do this in TreeSelectionListener / valueChanged. In other words I have the TreeSelectionEvent, the node, the path..

    Thank you in advance.

  2. #2
    lisichka's Avatar
    lisichka is offline Member
    Join Date
    Feb 2012
    Location
    Greece
    Posts
    5
    Rep Power
    0

    Default Re: Automatically select parent node(s) of a leaf in a JTree with checkboxes

    I am a step closer, because I now have the ancestor nodes of my leaf

    Java Code:
    tree.addTreeSelectionListener(new TreeSelectionListener() {
                @Override
                public void valueChanged(TreeSelectionEvent e) {
                    CheckNode node = (CheckNode) e.getPath().getLastPathComponent();
                    CheckNode parent = (CheckNode) (node.getParent());
                    
                    if (parent != null) {
                        tree.setSelectionPath(new TreePath(parent));
    //                    parent.setSelected(true);
                    }
                    System.out.println("You selected " + node);
                }
            });
    CheckNode extends DefaultMutableTreeNode.
    In the example above, if I activate the commented-out line, then all previous nodes until the root node become selected (which is not what I would wish for), yet the leaf itself becomes deselected.

    Any ideas?

  3. #3
    doWhile is offline Moderator
    Join Date
    Jul 2010
    Location
    California
    Posts
    1,642
    Rep Power
    7

    Default Re: Automatically select parent node(s) of a leaf in a JTree with checkboxes

    I am unclear what your requirements are...do you wish to keep the current selection and add the parent nodes to the selection? If so, use addSelectionPath rather than setSelectionPath

  4. #4
    lisichka's Avatar
    lisichka is offline Member
    Join Date
    Feb 2012
    Location
    Greece
    Posts
    5
    Rep Power
    0

    Default Re: Automatically select parent node(s) of a leaf in a JTree with checkboxes

    doWhile,
    first of all, thank you for your answer.

    Then, let me clarify what I meant.

    Let's say, that I have a JTree like this, with checkboxes on each node:

    1
    |_ 1.1
    | |_1.1.1
    | |_1.1.2
    |_ 1.2
    |_1.2.1
    |_1.2.2

    What I ideally want, is upon checking leaf value 1.2.2, to have automatically selected parent node 1.2 and root node 1.

    I tried to use addSelectionPath instead of setSelectionPath in my TreeSelectionEvent, but I'm still getting the same result - only the node 1.2.2 is selected. I was trying to find any reference on the internet but couldn't find something. Therefore, I wonder whether I'm trying to do it in an unorthodox way?

  5. #5
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,237
    Rep Power
    19

    Default Re: Automatically select parent node(s) of a leaf in a JTree with checkboxes

    Matbe you'd be better off trying a custom TreeCellRenderer that renders a selected appearance for all the nodes in each TreePath returned by getSelectedPaths()

    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  6. #6
    lisichka's Avatar
    lisichka is offline Member
    Join Date
    Feb 2012
    Location
    Greece
    Posts
    5
    Rep Power
    0

    Default Re: Automatically select parent node(s) of a leaf in a JTree with checkboxes

    Just in case someone finds the source code more helpful in order to come up with a solution/suggestion, I have created a tester class, as part of my program, in order to provide you with some source code.

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Toolkit;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.ArrayList;
    import java.util.Enumeration;
    
    
    
    import javax.swing.Icon;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.UIManager;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.plaf.ColorUIResource;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeCellRenderer;
    import javax.swing.tree.TreeNode;
    import javax.swing.tree.TreePath;
    import javax.swing.tree.TreeSelectionModel;
    
    
    public class TestCheckTree extends JFrame {
    	private static final long serialVersionUID = -8273897088841045672L;
    	protected CheckNode[] nodes = null;
    	protected JTree tree = null;
    	
    	public static void main(String[] args) {
    		try {
    			UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    		}
    		catch (Exception evt) {
    			evt.printStackTrace();
    		}
    		new TestCheckTree();
    	}
    	
    	
    	public TestCheckTree() {
    		initGUI();
    	}
    	
    	
    	private void initGUI() {
    		//Some data
    	    String[] strs = {"swing",     // 0
    			     "plaf",      // 1
    			     "basic",     // 2
    			     "metal",     // 3
    			     "JTree",     // 4
    			     "plaf",      // 5
    			     "motif"};    // 6
    	                                             
    	    CheckNode[] nodes = new CheckNode[strs.length];
    	    for (int i = 0; i < strs.length; i++) {
    	      nodes[i] = new CheckNode(strs[i]); 
    	    }
    	    nodes[0].add(nodes[1]);
    	    nodes[1].add(nodes[2]);
    	    nodes[1].add(nodes[3]);
    	    nodes[0].add(nodes[4]);
    	    nodes[0].add(nodes[5]);
    	    nodes[5].add(nodes[6]);
    	
    		
    		tree = new JTree(nodes[0]);
    		CustomTreeModel treeModel = new CustomTreeModel(nodes[0]);
    		treeModel.setTree(tree);
    		tree.setModel(treeModel);
    		
    		tree.setCellRenderer(new CheckRenderer());
    		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    		tree.putClientProperty("JTree.lineStyle", "Angled");
    		tree.addMouseListener(new NodeSelectionListener(tree));
    	    tree.addTreeSelectionListener(new TreeSelectionListener() {
    	    	@Override
    	    	public void valueChanged(TreeSelectionEvent e) {
    	    		CheckNode node = (CheckNode) e.getPath().getLastPathComponent();
    	    		CheckNode parent = (CheckNode) (node.getParent());
    	    		
    	    		if (parent != null) {
    		    		tree.addSelectionPath(new TreePath(parent));
    		    		
    //		    		parent.setSelected(true);
    	    		}
    	    		System.out.println("You selected " + node);
    	    	}
    	    });
    
    		addPanels();
    		showGUI();
    
    		
    		this.addWindowListener(new WindowAdapter() {
    			public void windowClosing(WindowEvent e) {
    				System.exit(0);
    			}
    		});
    	}
    
    	protected JScrollPane getMainTreeScrollPanel() {
    		return new JScrollPane(tree);	
    	}
    	
    	protected void addPanels() {
    		JPanel jpMain = new JPanel();
    		
    		jpMain.setLayout(new BorderLayout());
    		jpMain.add(getMainTreeScrollPanel(), BorderLayout.CENTER);
    
    		getContentPane().add(jpMain, BorderLayout.CENTER);
    	}
    
    	private void showGUI() {
    		this.addWindowListener(new WindowAdapter() {
    			public void windowClosing(WindowEvent e) {
    				System.exit(0);
    			}
    		});
    		setWindowSize();
    		centerFrame();
    		this.setVisible(true);
    	}
    	
    	protected void setWindowSize() {
    		this.setSize(800, 500);
    	}
    
    	private void centerFrame() {
    		Toolkit tk = Toolkit.getDefaultToolkit();
    		Dimension screenSize = tk.getScreenSize();
    		int screenHeight = screenSize.height;
    		int screenWidth = screenSize.width;
    		setSize(screenWidth / 2, screenHeight / 2);
    		setLocation(screenWidth / 4, screenHeight / 4);
    	}
    	class CustomTreeModel extends DefaultTreeModel {
    		private static final long serialVersionUID = -544777733041829040L;
    		private CheckNode rootNode = null, node = null;
    		private JTree whichTree = null;
    
    		public CustomTreeModel(TreeNode root) {
    			super(root);
    			this.rootNode = (CheckNode) root;
    		}
    
    		@SuppressWarnings("rawtypes")
    		@Override
    		public void reload() {
    			super.reload();
    
    			//Get the enumeration
    			Enumeration rootEnum = rootNode.breadthFirstEnumeration();
    
    			//iterate through the enumeration
    			while(rootEnum.hasMoreElements()) {
    				//get the node
    				node = (CheckNode)rootEnum.nextElement();
    
    				if (node.isSelected) {
    					//do something
    				}
    			}
    		}
    		
    		protected void setTree(JTree tree) {
    			this.whichTree = tree;
    		}
    	}
    	
    	class NodeSelectionListener extends MouseAdapter {
    		JTree tree;
    
    		NodeSelectionListener(JTree tree) {
    			this.tree = tree;
    		}
    
    		@Override
    		public void mouseClicked(MouseEvent e) {
    			int x = e.getX();
    			int y = e.getY();
    			int row = tree.getRowForLocation(x, y);
    			
                if (row == -1) {//When user clicks on the "empty surface"  
                    tree.clearSelection();
                }
                else {
        			TreePath  path = tree.getPathForRow(row);
        			//TreePath  path = tree.getSelectionPath();
        			if (path != null) {
        				CheckNode node = (CheckNode)path.getLastPathComponent();
        				boolean isSelected = ! (node.isSelected());
        				node.setSelected(isSelected);
        				if (node.getSelectionMode() == CheckNode.DIG_IN_SELECTION) {
        					if ( isSelected) {
        						tree.expandPath(path);
        					} else {
        						tree.collapsePath(path);
        					}
        				}
        				((DefaultTreeModel) tree.getModel()).nodeChanged(node);
        				// I need to revalidate if node is root.
        				if (row == 0) {
        					tree.revalidate();
        					tree.repaint();
        				}
        			}
                }
    		}
    	}
    }
    
    class CheckRenderer extends JPanel implements TreeCellRenderer {
    	private static final long serialVersionUID = -2965138434526530726L;
    
    	protected JCheckBox check;
    
    	protected TreeLabel label;
    
    	public CheckRenderer() {
    		setLayout(null);
    		add(check = new JCheckBox());
    		add(label = new TreeLabel());
    	    
    	    check.setBackground(UIManager.getColor("Tree.textBackground"));
    		label.setForeground(UIManager.getColor("Tree.textForeground"));
    		
    
    	}
    
    	public Component getTreeCellRendererComponent(JTree tree, Object value,
    			boolean isSelected, boolean expanded, boolean leaf, int row,
    			boolean hasFocus) {
    		String stringValue = tree.convertValueToText(value, isSelected, expanded, leaf, row, hasFocus);
    		
    		boolean treeIsEnabled = tree.isEnabled(); 
    	    boolean nodeIsEnabled = ((CheckNode)value).isEnabled(); 
    	    boolean isEnabled = (treeIsEnabled && nodeIsEnabled);
    	    setEnabled(isEnabled);
    	    
    //		setEnabled(tree.isEnabled());
    		check.setSelected(((CheckNode) value).isSelected());
    		label.setFont(tree.getFont());
    		label.setText(stringValue);
    		label.setSelected(isSelected);
    		label.setFocus(hasFocus);
    		
    		setBackground( isSelected ? Color.LIGHT_GRAY : Color.WHITE );
    		setForeground( isSelected ? Color.WHITE : Color.BLACK );
    		
    	    
    	    
    		if (leaf) {
    			label.setIcon(UIManager.getIcon("Tree.leafIcon"));
    		} else if (expanded) {
    			label.setIcon(UIManager.getIcon("Tree.openIcon"));
    		} else {
    			label.setIcon(UIManager.getIcon("Tree.closedIcon"));
    		}
    		return this;
    	}
    
    	public Dimension getPreferredSize() {
    		Dimension d_check = check.getPreferredSize();
    		Dimension d_label = label.getPreferredSize();
    		return new Dimension(d_check.width + d_label.width, (d_check.height < d_label.height ? d_label.height : d_check.height));
    	}
    
    	public void doLayout() {
    		Dimension d_check = check.getPreferredSize();
    		Dimension d_label = label.getPreferredSize();
    		int y_check = 0;
    		int y_label = 0;
    		if (d_check.height < d_label.height) {
    			y_check = (d_label.height - d_check.height) / 2;
    		} else {
    			y_label = (d_check.height - d_label.height) / 2;
    		}
    		check.setLocation(0, y_check);
    		check.setBounds(0, y_check, d_check.width, d_check.height);
    		label.setLocation(d_check.width, y_label);
    		label.setBounds(d_check.width, y_label, d_label.width, d_label.height);
    	}
    
    	public void setBackground(Color color) {
    		if (color instanceof ColorUIResource)
    			color = null;
    		super.setBackground(color);
    	}
    
    
    	public class TreeLabel extends JLabel {
    		private static final long serialVersionUID = 140492962184515362L;
    
    		boolean isSelected;
    
    		boolean hasFocus;
    
    		public TreeLabel() {
    		}
    
    		public void setBackground(Color color) {
    			if (color instanceof ColorUIResource)
    				color = null;
    			super.setBackground(color);
    		}
    
    
    		public void paint(Graphics g) {
    			String str;
    			if ((str = getText()) != null) {
    				if (0 < str.length()) {
    					if (isSelected) {
    						g.setColor(UIManager.getColor("Tree.selectionBackground"));
    					} 
    					else {
    						g.setColor(UIManager.getColor("Tree.textBackground"));
    					}
    					Dimension d = getPreferredSize();
    					int imageOffset = 0;
    					Icon currentI = getIcon();
    					if (currentI != null) {
    						imageOffset = currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
    					}
    					g.fillRect(imageOffset, 0, d.width - 1 - imageOffset, d.height);
    					if (hasFocus) {
    						g.setColor(UIManager.getColor("Tree.selectionBorderColor"));
    						g.drawRect(imageOffset, 0, d.width - 1 - imageOffset, d.height - 1);
    					}
    				}
    			}
    			super.paint(g);
    		}
    
    		public Dimension getPreferredSize() {
    			Dimension retDimension = super.getPreferredSize();
    			if (retDimension != null) {
    				retDimension = new Dimension(retDimension.width + 3, retDimension.height);
    			}
    			return retDimension;
    		}
    
    		public void setSelected(boolean isSelected) {
    			this.isSelected = isSelected;
    		}
    
    		public void setFocus(boolean hasFocus) {
    			this.hasFocus = hasFocus;
    		}
    	}
    }
    class CheckNode extends DefaultMutableTreeNode {
    	private static final long serialVersionUID = 6779132258840505119L;
    
    	public final static int SINGLE_SELECTION = 0;
    	public final static int DIG_IN_SELECTION = 4;
    	protected int selectionMode;
    	protected boolean isSelected;
    	protected boolean enabled = true;
    	boolean isOn = false;
    	boolean isPartiallyOn = false;
    
    	public CheckNode() {
    		this(null);
    	}
    
    	public CheckNode(Object userObject) {
    		this(userObject, true, false);
    	}
    
    	public CheckNode(Object userObject, boolean isEnabled) {
    		this(userObject, true, false, isEnabled);
    	}
    
    	public CheckNode(Object userObject, boolean allowsChildren, boolean isSelected) {
    		super(userObject, allowsChildren);
    		this.isSelected = isSelected;
    		setSelectionMode(DIG_IN_SELECTION);
    	}
    	
    	public CheckNode(Object userObject, boolean allowsChildren, boolean isSelected, boolean isEnabled) {
    		super(userObject, allowsChildren);
    		this.isSelected = isSelected;
    		this.enabled = isEnabled;
    		setSelectionMode(DIG_IN_SELECTION);
    	}
    
    	public void setSelectionMode(int mode) {
    		selectionMode = mode;
    	}
    
    	public int getSelectionMode() {
    		return selectionMode;
    	}
    
    	@SuppressWarnings({ "unchecked", "rawtypes" })
    	public void setSelected(boolean isSelected) {
    		this.isSelected = isSelected;
    		
    		if ((selectionMode == DIG_IN_SELECTION) && (children != null)) {
    			Enumeration e = children.elements();
    			while (e.hasMoreElements()) {
    				CheckNode node = (CheckNode) e.nextElement();
    				node.setSelected(isSelected);
    			}
    		}
    	}
    
    
    	public boolean isSelected() {
    		return isSelected;
    	}
    
    	public void setEnabled(boolean enabled) {
    		this.enabled = enabled;
    	}
    
    	public boolean isEnabled() {
    		return enabled;
    	}
    }
    Since my post and doWhile's post was lost I will try to remember what he asked me. I think, he asked me about Single, Contiguous or Discontiguous tree selection. Well, I tried all three options, but still no (desired) result.

Similar Threads

  1. action to a node in a jtree
    By sniffer139 in forum AWT / Swing
    Replies: 4
    Last Post: 08-29-2014, 03:51 PM
  2. Access Parent and child node
    By emyk in forum Advanced Java
    Replies: 0
    Last Post: 05-02-2011, 11:16 PM
  3. Multiple components as one node in JTree
    By Amnuriak in forum AWT / Swing
    Replies: 8
    Last Post: 11-04-2009, 02:47 PM
  4. How to add JCheckbox as a node in JTree
    By shajuantony in forum New To Java
    Replies: 0
    Last Post: 04-09-2009, 07:19 AM
  5. Node selection in jtree
    By Preethi in forum AWT / Swing
    Replies: 4
    Last Post: 06-19-2008, 11:25 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •