JTree's setRootVisible method

I have extended the DefaultTreeModel class and made my own model.
I have used the nodeWereInserted and nodeWereRemoved to notify the model changes.
Every thing worked perfect: the tree responded to all kind of changes: insertion, deletion.
But when I invoked the method: setRootVisible(false) the tree is completely invisible.
I have seen that this behavior was reported as a bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4699927
But Sun says that this is not a bug, but they are very confusing in their arguments in saying so.
Sincerely while the model is working perfectely I don't see why a simple visual tweakening has this effect.
;)

I have found the answer. There is no problem in fact, but there is a small trick.
When the root is invisible and the tree is empty - not realy empty, it has the root, but the root is a leaf - when a node is added as a child to the root then you must expand the root programatically. You can't expand it visually - by keyboard or mouse.
To do this you must add a TreeModelListener on the tree's model and in the appropiate methods - treeNodesInserted by example - expand the root using the JTree's expandPath(TreePath path) method.
Using the method above the tree will corectly display its nodes.

Similar Messages

  • Help with JTree's opaque methods

    I have been looking through the methods provided for JTree in Netbeans GUIBuilder and I do not see accessor methods for actions like insertion, retrieval, deletion and replacement. I am looking for something like this.
    JTree.insert('object', JTree.getSelectedNode());
    JTree.getSelectedNode().getObject();
    JTree.deleteNode(JTree.getSelected());
    JTree. supplantObject(‘object’, JTree.getSelectedNode());
    JTree.insert('object', JTree.getSelectedNode()) should accept to inputs; the object you wish to insert and the location you wish to insert it. JTree.getSelectedNode() would be an accessor method returning the selected node. The insert would have to find the next available element in the LinkedList, array, hashtable, stack, (or whatever it uses) and inserts the object.
    JTree.getSelectedNode().getObject(); I assume that if I have “apple” selected in the JTree, “apple” will be returned.
    JTree.deleteNode(JTree.getSelected()); deleting the node wipes out all its children as well.
    JTree. supplantObject(‘object’, JTree.getSelectedNode()); overwrites the object in the selected with a new object.
    These seem like the more obvious accessor methods and I am astonished to find them missing or named something inconsistent with java standards.
    So I guess my question is, what are the equivalent method names for the aforementioned methods?
    BM

    Take a look at [http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/tree/DefaultMutableTreeNode.html|http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/tree/DefaultMutableTreeNode.html] which has most of the methods that you are interested in. A JTree has a single root node, which by default is of this type.

  • Jtree's ValueChange method problem

    my code are as follow:
    i'm now doing a JTree which will list all the directory in the computers(every node is a directory) ..
    When i click on each node, i wanna it to display all files names in this directory ...
    but i just fail that statement:
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
    this statement will cause an error
    anyone know how to solve it ??
    Thanks very very much !!!
    my codes:
    import java.io.*;
    import javax.swing.*;
    import java.awt.*;
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.awt.event.*;
    public class PDThumnailer extends JFrame {
         private JTree tree;
         private JScrollPane scpTree;
         private JSplitPane split;
         private JPanel leftPane;
         public PDThumnailer() {
              super();
              Vector dirs = new Vector();
              File[] roots = File.listRoots();
              for(int i=0; i<roots.length; i++) {
                   dirs.add(roots);
              leftPane = new JPanel();
              tree = new JTree(new FileTreeModel(dirs));
              tree.setCellRenderer(new FileTreeCellRenderer());
              tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
              scpTree = new JScrollPane(tree);
              split = new JSplitPane(1, scpTree, leftPane);
              split.setOneTouchExpandable(true);
    split.setDividerLocation(200);
              this.getContentPane().add(split);
              this.setSize(550,400);
              this.setVisible(true);
              this.addWindowListener(new WindowAdapter() {
                        public void windowClosing(WindowEvent e) {
                             //setVisible(false);
                             System.exit(-1);
              tree.addTreeSelectionListener(new TreeSelectionListener() {
                        public void valueChanged(TreeSelectionEvent e) {
                                  DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
                                  if (node == null)
                                       return;
                                  Object nodeInfo = node.getUserObject();
                                  System.out.println("nodeInfo");
                                  if(nodeInfo instanceof File) {
                                       File file = (File) nodeInfo;
                                       File[] allFiles = file.listFiles();
                                       for(int i=0;i<allFiles.length;i++)
                                            System.out.println(allFiles[i].getName());
         public static void main(String[] arg){
                   new PDThumnailer();
    class FileTreeCellRenderer extends JLabel implements TreeCellRenderer {
    public FileTreeCellRenderer() {
         super("", JLabel.LEFT);
         this.setOpaque(true);
    /* implements TreeCellRenderer BEGIN */
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
         if (selected) {
              this.setBackground(Color.black);
              this.setForeground(Color.white);
         else {
              this.setBackground(Color.white);
              this.setForeground(Color.black);
         if (value instanceof File) {
              File file = (File) value;
              if (file.isDirectory()) {
                        this.setText(file.getPath());
                        this.setIcon(new ImageIcon("icon/folder.gif"));
              else {
                        this.setText(file.getName());
                        this.setIcon(new ImageIcon("icon/file.gif"));
         else {
                   setText("");
         return this;
    /* implements TreeCellRenderer END */
    class FileTreeModel implements TreeModel {
    private Vector dirs;
    public FileTreeModel(Vector dirs) {
    this.dirs = dirs;
    /* implements TreeModel BEGIN */
    public void addTreeModelListener(TreeModelListener l) {
    public Object getChild(Object parent, int index) {
    if (parent instanceof Vector) {
    return dirs.get(index);
    else if (parent instanceof File) {
    File file = (File) parent;
    if (file.isDirectory()) {
    File[] allFiles = file.listFiles(new DirectoryFilter());
    if (allFiles != null) {
              return allFiles[index];
    return null;
    public int getChildCount(Object parent) {
    if (parent instanceof Vector) {
    return dirs.size();
    else if (parent instanceof File) {
    File file = (File) parent;
    if (file.isDirectory()) {
    File[] allFiles = file.listFiles(new DirectoryFilter());
         int count =0;
    if (allFiles != null) {
    return allFiles.length;
    return 0;
    public int getIndexOfChild(Object parent, Object child) {
         if (parent instanceof Vector) {
              return dirs.indexOf(child);
         else if (parent instanceof File) {
              File file = (File) parent;
                   if (file.isDirectory()) {
                             File[] allFiles = file.listFiles(new DirectoryFilter());
                             if (allFiles != null) {
                                  for (int i=0; i<allFiles.length; i++) {
                                       if (child.equals(allFiles[i])) {
                                                 return i;
         return -1;
    public Object getRoot() {
    return this.dirs;
    public boolean isLeaf(Object node) {
         if (node instanceof Vector) {
              return dirs.isEmpty();
         else if (node instanceof File) {
         File file = (File) node;
         if (file.isDirectory()) {
                   File[] allFiles = file.listFiles(new DirectoryFilter());
                   if (allFiles != null) {
                        return allFiles.length == 0;
         return true;
    public void removeTreeModelListener(TreeModelListener l) {
    public void valueForPathChanged(TreePath path, Object newValue) {
    /* implements TreeModel END */
    class DirectoryFilter implements FileFilter
         public boolean accept(File f) {
              return f.isDirectory();

    Replace this line with
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)(event.getPath().getLastPathComponent());Tell me whether that helps to solve your problem.

  • Comparing Two Jtree Objects

    Hi
    I had constructed two JTree objects. Now i want to find the difference between these two JTree's Node wise.I dont have any idea how to proceed further.If some one help me in this regard i would be very thankful.
    -Rosy

    The JTree component handles the 'view' side of things. The actual data it displays is held in a TreeModel. You can create your own and pass it to the JTree when you create it otherwise a DefaultTreeModel is created for you by the JTree.
    What I'm getting at is that to achieve your aim you want to compare the TreeModels rather than the JTrees.
    If you haven't created your own, you can get it from the JTree using jTree.getModel()
    Calling methods on each model and comparing the results will achieve your aim.

  • Trouble with JTree's and autmoatically expanding nodes

    I am writing an application which uses a JTree as a method of browsing through a certain structure (like a file system). I am having a little trouble though, with a number of small issues, which I am finding hard to get answers through searches (and have spent a fair while searching). In navigating the tree, I want to be able to automatically expand nodes.
    Firstly, I want the Root node to automatically be expanded. I cannot see ways of doing this. I have seen references to EXPANDED being set for the JTree constructor, but I cannot see any reference in the 1.6 API for this.
    Secondly, I want to be able to expand or hide the contents of nodes through other means than clicking on the icon to the left of a non-leaf-node. For example a button that would hide the contents of (i.e. close) the currently selected node. Code such as:
    myNode.setExpanded(true);
    myNode.setExpanded(false);and
    myNode.isExpanded();

    That's the ticket - again something I had seen, but had been using in the wrong way, but your suggestion has helped me get it right. I was trying to expand the path before any more nodes were added to the root node. Then nodes are added, and the application loaded with the root node collapsed. So now I have placed the call at the end of the recursive call to populate the tree.
    Thanks again.

  • How remove (or change) children inside a JTree

    hi,
    I did a program where there are informations with a structure of dependence that should be showed inside JTree components.
    I realized this purpose in my program .
    But I am findind very difficult (after having put the information inside the JTre in the start) to show them again inside the JTrees when they are changed.
    I don't know how to remove or change the informations after they are put on the children of the JTree using the methods that I found in the documentation to reach this purpose...
    I need some help ...
    To explain well my problem, and facilitate the helpers, I post some code that show my problem..
    The program show a GUI with some JTrees.
    The informations are contained in two strings, and in the GUI are also two buttons that can load the informations inside the JTree when they are clicked.
    Thank you in advance
    regards
    tonyMrsangelo
    public class JTree_TryToUseIt_ChangingNodes extends javax.swing.JFrame {
        private PanelFulViewConteiner jPanelFulViewConteiner;
        Dimension dimPrefArcPanels = new Dimension(910, 150);
        Dimension dimMinArcPanels = new Dimension(700, 100);
        Dimension dimPrefSemiArcPanels = new Dimension(850, 140);
        Dimension dimMinSemiArcPanels = new Dimension(550, 90);
        Dimension dimPrefBodyXpicPanels = new Dimension(900, 150);
        Dimension dimMinBodyXpicPanels = new Dimension(700, 150);
        Dimension treePrefDim = new Dimension(90, 110); //
        Dimension treeMinDim = new Dimension(60, 110);
        PanelToShowTrees panel_trees;
        public JTree_TryToUseIt_ChangingNodes() {
            getContentPane().setLayout(new GridBagLayout());
            GridBagConstraints gBC = new GridBagConstraints();
            jPanelFulViewConteiner = new PanelFulViewConteiner();
            gBC.gridx = 0;
            gBC.gridy = 0;
            gBC.gridwidth = 10;
            add(jPanelFulViewConteiner, new GridBagConstraints());
            gBC.gridx = 0;
            gBC.gridy = 1;
            gBC.gridwidth = 10;
            pack();
            panel_trees = this.jPanelFulViewConteiner.jPanelFulContainerTop.panelToShowTrees;
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setLocation(50, 50);
            setVisible(true);
        private void fillTrees(String[] strings) {
            collapseTrees();
            removeNodes();
            for (int index = 0; index < strings.length; index++) {
                DefaultMutableTreeNode dmt = new DefaultMutableTreeNode(strings[index]);
                String knotStr = strings[index].substring(0, 1);
                int knot = -1;
                try {
                    knot = Integer.parseInt(knotStr);
                } catch (NumberFormatException e) {
                panel_trees.root_Node[knot].add(dmt);
                panel_trees.validate();
                panel_trees.repaint();
            collapseTrees();
        void collapseTrees() {
            for (int i = 0; i < 8; i++) {
                panel_trees.jTree.collapseRow(0);
    panel_trees.jTree[i].expandRow(0);
    panel_trees.validate();
    panel_trees.repaint();
    void removeNodes() {
    for (int i = 0; i < 8; i++) {
    panel_trees.jTree[i].removeAll();
    panel_trees.validate();
    panel_trees.repaint();
    public static void main(String args[]) {
    JTree_TryToUseIt_ChangingNodes xx = new JTree_TryToUseIt_ChangingNodes();
    class PanelFulViewConteiner extends JPanel {
    PanelFulContainerTop jPanelFulContainerTop;
    PanelFulContainerBottom jPanelFulContainerBottom;
    public PanelFulViewConteiner() {
    GridBagLayout gbl = new GridBagLayout();
    this.setLayout(gbl);
    GridBagConstraints gBC = new GridBagConstraints();
    jPanelFulContainerTop = new PanelFulContainerTop();
    gBC.gridx = 0;
    gBC.gridy = 0;
    add(jPanelFulContainerTop, gBC);
    jPanelFulContainerBottom = new PanelFulContainerBottom();
    gBC.gridx = 0;
    gBC.gridy = 2;
    add(jPanelFulContainerBottom, gBC);
    class PanelFulContainerTop extends JPanel {
    PanelToShowTrees panelToShowTrees;
    public PanelFulContainerTop() { // costruttore
    this.setMinimumSize(dimMinArcPanels);
    this.setPreferredSize(dimPrefArcPanels);
    setLayout(new FlowLayout());
    panelToShowTrees = new PanelToShowTrees();
    add(panelToShowTrees);
    }// costruttore
    class PanelFulContainerBottom extends JPanel {
    JButton but1 = new JButton("load string1");
    JButton but2 = new JButton("load string2");
    String[] str1 = {"0-AAA", "0-BBBBBB", "2-CCCCC", "2-DDDDDD", "2-EEEEEEE", "5-FFFFFF", "5-GGGGGG", "5-HHHHHH", "7-IIIIII", "7-KKKKKKK", "7-LLLLLL", "7-MMMMMM"};
    String[] str2 = {"0-aaaaa", "0-bbbbb", "0-cccc", "2-ddddd", "2-eeee", "3-ffffff", "3-gggggg", "3-hhhhh", "4-iiiiii", "4-kkkkk", "7-lllllll", "7-mmmmm", "7-nnnnn"};
    public PanelFulContainerBottom() {// costruttore
    this.setMinimumSize(dimMinArcPanels);
    this.setPreferredSize(dimPrefArcPanels);
    add(but1);
    but1.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    fillTrees(str1);
    add(but2);
    but2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    fillTrees(str2);
    class PanelToShowTrees extends JPanel {
    JScrollPane jScrollPane[];
    JTree jTree[];
    DefaultMutableTreeNode[] root_Node;
    public PanelToShowTrees() {
    this.setMinimumSize(dimMinSemiArcPanels);
    this.setPreferredSize(dimPrefSemiArcPanels);
    setLayout(new FlowLayout());
    jScrollPane = new JScrollPane[8];
    jTree = new JTree[8];
    root_Node = new DefaultMutableTreeNode[8];
    for (int i = 0; i < 8; i++) {
    root_Node[i] = new DefaultMutableTreeNode(" " + (8 - i));
    jTree[i] = new JTree(root_Node[i]);
    jScrollPane[i] = new JScrollPane();
    jScrollPane[i].setViewportView(jTree[i]);
    add(jScrollPane[i]);
    jScrollPane[i].setPreferredSize(treePrefDim);
    jScrollPane[i].setMinimumSize(treeMinDim);
    jTree[i].addTreeSelectionListener(new TreeSelectionListener() {
    public void valueChanged(TreeSelectionEvent e) {
    showContentOfTheTree(e);
    private void showContentOfTheTree(TreeSelectionEvent e) {
    String stringaGotFromEvent = e.getPath().toString();
    JOptionPane.showMessageDialog(rootPane, "found =---> " + stringaGotFromEvent);

    hi Andre,
    thank you for answering me.
    I have not much practice with JTrees so I find some difficulty to use it...
    After I got your advice, I made changed a little the design of my program..
    This it is a program for management of a dentist office, and I would show in 8 JTrees (every jTree root represents the teeth in a dental arch) the treatments that each tooth got.
    How I said, the 8 JTree roots are representing the teeth, and in this architecture the problem is:
    - to add a node to a tree root to indicate a treatment for that tooth;
    - to delete all the children from a jTree root before beginning to add new child, before writing again treatments, when the informations are changed.
    Following your help, I made this two functions to reach this purpose:
    private void assingTreatmentToTooth(int toothNmbr, String strTreatment) {
            DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(strTreatment); // new treatment to add
            DefaultTreeModel model = (DefaultTreeModel) panel_trees.jTreeXdentalRoots[toothNmbr].getModel(); // get model for the root Tree
            DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) model.getRoot();
            model.insertNodeInto(newChild, parentNode, 0); // always assign 0 as first node
        } // assingTreatmentToTooth()
    private void removeTreatmentFromAtooth(int toothNmbr, int childNmbr) {
            DefaultTreeModel model = (DefaultTreeModel) panel_trees.jTreeXdentalRoots[toothNmbr].getModel();  // get model for the root Tree
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(model, childNmbr);
            model.removeNodeFromParent(child);
        } // removeTreatmentToTooth()when the second function is executed, I get this error:
    Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.tree.DefaultTreeModel cannot be cast to javax.swing.tree.TreeNode
    at the line : DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(model, childNmbr);
    DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(model, childNmbr);
    could you tell me what is wrong ?
    regards
    TonyMrsangelo

  • JTree Double Click

    Is there any way I can remove the default double click behaviour for a node in a JTree? Currently it expands or collapses the node, but I want it to do something else. I have set a listener up so it can do the new task, but I want to remove the expand/collapse behaviour as well.

    But it isn't....
    With the TreeWillExpandListener I cannot distinguish between the two expansion methods.
    However, I have found another, extremely simple way of doing what I want, using the JTree.setToggleClickCount(int) method. This sets the number of clicks needed to expand the node (but does not affect clicking on the + box). By setting this to a high number, I can prevent double clicks from expanding nodes, thus allowing my own double click listener to do the stuff I need.

  • Updating Jtree problem

    I have a JTree which has to refresh (show the new node) on click of button when ever i am adding a new node.
    I am adding node by the DefaultTreeModel : insertNodeInto() method.I added the TreeModelListener to treeModel and also called the nodeStructureChanged(parent) method...not working ...
    I then tried to override the treeNodesInserted() method by invoking tree.scrollPathToVisible(new TreePath(childNode.getPath()));
    ...did not work...
    I went thru the forum and found only similar answers...Can any one please help....In some URL i found that we need to add TreeExpansionListener ..but i am confused about it.

    I did that now ..but still its not reloading..I am sending the code snippet below:
    public class TreeModel {
    DefaultMutableTreeNode childNode;
    DefaultTreeModel jtm;
    JTree jt;
    //another method calls this method
    public void UpdateTree(String sitenm) {
    childNode = new DefaultMutableTreeNode((Object) sitenm);
    DefaultMutableTreeNode parent=null;
    try {
    parent = new DefaultMutableTreeNode(jt.getSelectionPath().getLastPathComponent());
    } catch (Exception e) {
    parent = (DefaultMutableTreeNode) jtm.getRoot();
    jtm.insertNodeInto(childNode, parent, parent.getChildCount());
    jtm.nodeStructureChanged(parent);
    //jt.scrollPathToVisible(new TreePath(childNode.getPath()));
    //jt.updateUI();
    jtm.reload();
    public class TreeListener implements TreeModelListener {
    public void treeNodesChanged(TreeModelEvent tme) {
    public void treeNodesInserted(TreeModelEvent tme) {
    jtm.reload();
    jt.scrollPathToVisible(new TreePath(childNode.getPath()));
    public void treeNodesRemoved(TreeModelEvent tme) {
    public void treeStructureChanged(TreeModelEvent tme) {
    I tried using reload method in both methods and also immediately after the insert action.Its working partially ..like when no node is selected it gets added to root node of tree..but when i select a node in tree and then try adding to it,Its not refreshing.Is there anything else that i will have to do.

  • Dont Understant this JTree Example.

    I have an example that I copied, and ran. The funny thing is that it works, but I don't see how it gets it root, and child node names, etc..
    Is it pulling its information in from somewhere else? Is there some sort of default example that it runs?
    I want to create a JTree from an XML file that this reads and looks something like this. device
       |
         -- Module 1
                  |
                  -- Status
                          |
                          -- Device
                          -- Network
                          -- Chassis
                          -- Resources
                  -- Project Manager
                  -- Project Editor
                  -- Administration
                          |
                          -- device
                          -- users
                          ... etc...I want to be able to a have 1 or more modules on a device. Maybe even 1 or more devices.
    Anyway I like the way it knows which node I have clicked on. What level, and name of each node.
    It is doing exactly what I want it to do. I just dont know how to add the components that I need.
    Here is the code.
    import java.awt.BorderLayout;
    import java.util.Enumeration;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.TreeModel;
    import javax.swing.tree.TreeNode;
    import javax.swing.tree.TreePath;
    public class MainClass
        public static void main(String args[])
            JFrame frame = new JFrame("Traverse Tree");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JTree tree = new JTree();
            tree.setRootVisible(true);
            TreeModel model = tree.getModel();
            Object rootObject = model.getRoot();
            if ((rootObject != null) &&
                    (rootObject instanceof DefaultMutableTreeNode))
                DefaultMutableTreeNode r = (DefaultMutableTreeNode) rootObject;
                printDescendents(r);
                Enumeration breadth = r.breadthFirstEnumeration();
                Enumeration depth = r.depthFirstEnumeration();
                Enumeration preOrder = r.preorderEnumeration();
                printEnumeration(breadth, "Breadth");
                printEnumeration(depth, "Depth");
                printEnumeration(preOrder, "Pre");
            TreeSelectionListener treeSelectionListener =
                    new TreeSelectionListener()
                public void valueChanged(TreeSelectionEvent treeSelectionEvent)
                    JTree treeSource = (JTree) treeSelectionEvent.getSource();
                    TreePath path = treeSource.getSelectionPath();
                    System.out.println(path);
                    System.out.println(path.getPath());
                    System.out.println(path.getParentPath());
                    System.out.println(((DefaultMutableTreeNode)
                        path.getLastPathComponent()).getUserObject());
                    System.out.println(path.getPathCount());
            tree.addTreeSelectionListener(treeSelectionListener);
            JScrollPane scrollPane = new JScrollPane(tree);
            frame.add(scrollPane, BorderLayout.CENTER);
            frame.setSize(300, 400);
            frame.setVisible(true);
        private static void printEnumeration(Enumeration e, String label)
            System.out.println("-----" + label + "-----");
            while (e.hasMoreElements())
                System.out.println(e.nextElement());
        public static void printDescendents(TreeNode root)
            System.out.println(root);
            Enumeration children = root.children();
            if (children != null)
                while (children.hasMoreElements())
                    printDescendents((TreeNode) children.nextElement());
    }please help
    orozcom

    JTree tree = new JTree();It comes with a sample model.
    In order to make a tree view of an XML file, use a SAX parser and retrieve each element from which you construct a tree node and attach it to your tree.

  • Useful Code of the Day:  Hideable Tree Nodes

    Someone posted about how they could selectively hide tree nodes, and I already had this AbstractTreeModel class (which does some things DefaultTreeModel does and some it doesn't) and a concrete subclass for TreeNode objects, so I was thinking how one could do hideable nodes. So I came up with this solution.
    There's 4 classes here:
    - AbstractTreeModel is the base for the concrete TreeNodeTreeModel
    - TreeNodeTreeModel extends AbstractTreeModel to support TreeNodes (DefautlMutableTreeNode, etc.)
    - HideableMutableTreeNode which is a DefautlMutableTreeNode subclass which has a visible field (with is/set methods, of course).
    - HideableTreeModel is the hideable model which is a subclass of TreeNodeTreeModel.
    A HideableMutableTreeNode can be set invisible directly, but the tree still needs to be notified to update. So it's best to use the methods in HideableTreeModel which set a node's visibility which notify the tree of changes accordingly. Methods are also provided to check a full path's visibility or ensure a node including all parent nodes are visible.
    A HideableTreeModel can take any TreeNode class, it doesn't have to be all HideableMutableTreeNodes, but only HideableMutableTreeNodes can be made invisible, of course. Any other TreeNode type would just be considered visible.
    Hiding nodes works basically by making the tree think there's less nodes then there are. And to do this, the node counts and child index search just works by looping thru the parent's children. This has potential perfomance drawbacks of course, since one has to loop thru the node's children to get nodes every time. This could be alleviated by not supporting non-hideable nodes changing the internal maintenance of HideableMutableTreeNode contents. But I'll leave that to whoever really needs it. It shouldn't be a problem if there are are a relatively small set of child nodes in any given parent.
    Also, note that the root node in the model cannot be made invisible, cuz it'd be redundant since JTree can be set to hide the root node.
    // *** HideableTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    * <code>HideableTreeModel</code> is an <code>TreeNodeTreeModel</code>
    * implementation for <code>HideableMutableTreeNode</code> objects.  The
    * model can also take any other <code>javax.swing.tree.TreeNode</code>
    * objects. 
    public class HideableTreeModel extends TreeNodeTreeModel {
          * Creates a new <code>HideableTreeModel</code> object.
          * @param  root  the root node
         public HideableTreeModel(TreeNode root) {
              super(root);
          * Checks if the specified node is visible.  A node can only be
          * hidden if the node is an instance of <code>HideableMutableTreeNode</code>.  <br />
          * <br />
          * Note that this only test the visibility of the specified node, not
          * whether a parent node is visible.  Use <code>isPathToNodeVisible(Object)</code>
          * to check if the full path is visible. 
          * @param  node  the node
          * @param  true if the node is visible, else false
         public boolean isNodeVisible(Object node) {
              if(node != getRoot()) {
                   if(node instanceof HideableMutableTreeNode) {
                        return ((HideableMutableTreeNode)node).isVisible();
              return true;
          * Sets the specified node to be hidden.  A node can only be made hidden
          * if the node is an instance of <code>HideableMutableTreeNode</code>.  <br />
          * <br />
          * Note that this method will notify the tree to reflect any changes to
          * node visibility.  <br />
          * <br />
          * Note that this will not alter the visibility of any nodes in the
          * specified node's path to the root node.  Use
          * <code>ensurePathToNodeVisible(Object)</code> instead to make sure the
          * full path down to that node is visible.  <br />
          * <br />
          * Note that this method will notify the tree to reflect any changes to
          * node visibility. 
          * @param  node  the node
          * @param  v     true for visible, false for hidden
          * @param  true if the node's visibility could actually change, else false
         public boolean setNodeVisible(Object node, boolean v) {
              // can't hide root
              if(node != getRoot()) {
                   if(node instanceof HideableMutableTreeNode) {
                        HideableMutableTreeNode n = (HideableMutableTreeNode)node;
                        // don't fix what ain't broke...
                        if(v != n.isVisible()) {
                             TreeNode parent = n.getParent();
                             if(v) {
                                  // need to get index after showing...
                                  n.setVisible(v);
                                  int index = getIndexOfChild(parent, n);
                                  super.nodeInserted(parent, n, index);
                             } else {
                                  // need to get index before hiding...
                                  int index = getIndexOfChild(parent, n);
                                  n.setVisible(v);
                                  super.nodeRemoved(parent, n, index);
                        return true;
              return false;
          * Checks if the specified node is visible and all nodes above it are
          * visible. 
          * @param  node  the node
          * @param  true if the path is visible, else false
         public boolean isPathToNodeVisible(Object node) {
              Object[] path = getPathToRoot(node);
              for(int i = 0; i < path.length; i++) {
                   if(!isNodeVisible(path)) {
                        return false;
              return true;
         * Sets the specified node and all nodes above it to be visible.
         * Note that this method will notify the tree to reflect any changes to
         * node visibility.
         * @param node the node
         public void ensurePathToNodeVisible(Object node) {
              Object[] path = getPathToRoot(node);
              for(int i = 0; i < path.length; i++) {
                   setNodeVisible(path[i], true);
         * Returns the child of parent at index index in the parent's child array.
         * @param parent the parent node
         * @param index the index
         * @return the child or null if no children
         public Object getChild(Object parent, int index) {
              if(parent instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   for(int i = 0, j = -1; i < p.getChildCount(); i++) {
                        TreeNode pc = (TreeNode)p.getChildAt(i);
                        if(isNodeVisible(pc)) {
                             j++;
                        if(j == index) {
                             return pc;
              return null;
         * Returns the number of children of parent.
         * @param parent the parent node
         * @return the child count
         public int getChildCount(Object parent) {
              int count = 0;
              if(parent instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   for(int i = 0; i < p.getChildCount(); i++) {
                        TreeNode pc = (TreeNode)p.getChildAt(i);
                        if(isNodeVisible(pc)) {
                             count++;
              return count;
         * Returns the index of child in parent.
         * @param parent the parent node
         * @param child the child node
         * @return the index of the child node in the parent
         public int getIndexOfChild(Object parent, Object child) {
              int index = -1;
              if(parent instanceof TreeNode && child instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   TreeNode c = (TreeNode)child;
                   if(isNodeVisible(c)) {
                        index = 0;
                        for(int i = 0; i < p.getChildCount(); i++) {
                             TreeNode pc = (TreeNode)p.getChildAt(i);
                             if(pc.equals(c)) {
                                  return index;
                             if(isNodeVisible(pc)) {
                                  index++;
              return index;
         * Main method for testing.
         * @param args the command-line arguments
         public static void main(String[] args) {
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              HideableMutableTreeNode root = new HideableMutableTreeNode("root");
              root.add(new HideableMutableTreeNode("child_1"));
              final HideableMutableTreeNode c2 = new HideableMutableTreeNode("child_2");
              c2.setVisible(false);
              final HideableMutableTreeNode c2a = new HideableMutableTreeNode("child_2_A");
              c2.add(c2a);
              c2.add(new HideableMutableTreeNode("child_2_B"));
              root.add(c2);
              HideableMutableTreeNode c3 = new HideableMutableTreeNode("child_3");
              HideableMutableTreeNode cC = new HideableMutableTreeNode("child_3_C");
              cC.setVisible(false);
              c3.add(cC);
              c3.add(new HideableMutableTreeNode("child_3_D"));
              root.add(c3);
              root.add(new HideableMutableTreeNode("child_4"));
              root.add(new HideableMutableTreeNode("child_5"));
              DefaultMutableTreeNode c6 = new DefaultMutableTreeNode("child_6");
              c6.add(new DefaultMutableTreeNode("child_6_A"));
              c6.add(new DefaultMutableTreeNode("child_6_B"));
              root.add(c6);
              final HideableTreeModel model = new HideableTreeModel(root);
              JTree tree = new JTree(model);
              f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
              JButton b = new JButton("toggle");
              b.addActionListener(new ActionListener() {
                   public void actionPerformed(ActionEvent e) {
                        model.setNodeVisible(c2, !model.isNodeVisible(c2));
                        //model.ensurePathToNodeVisible(c2a);
              f.getContentPane().add(b, BorderLayout.SOUTH);
              f.pack();
              f.setSize(300, 500);
              f.show();
    // *** HideableMutableTreeNode ***
    import javax.swing.*;
    import javax.swing.tree.*;
    * <code>HideableMutableTreeNode</code> is a <code>DefaultMutableTreeNode</code>
    * implementation that works with <code>HideableTreeModel</code>.
    public class HideableMutableTreeNode extends DefaultMutableTreeNode {
         * The node is visible flag.
         public boolean visible = true;
         * Creates a tree node that has no parent and no children, but which
         * allows children.
         public HideableMutableTreeNode() {
              super();
         * Creates a tree node with no parent, no children, but which allows
         * children, and initializes it with the specified user object.
         * @param userObject - an Object provided by the user that
         * constitutes the node's data
         public HideableMutableTreeNode(Object userObject) {
              super(userObject);
         * Creates a tree node with no parent, no children, initialized with the
         * specified user object, and that allows children only if specified.
         * @param userObject - an Object provided by the user that
         * constitutes the node's data
         * @param allowsChildren - if true, the node is allowed to have child
         * nodes -- otherwise, it is always a leaf node
         public HideableMutableTreeNode(Object userObject, boolean allowsChildren) {
              super(userObject, allowsChildren);
         * Checks if the node is visible.
         * @return true if the node is visible, else false
         public boolean isVisible() {
              return this.visible;
         * Sets if the node is visible.
         * @param v true if the node is visible, else false
         public void setVisible(boolean v) {
              this.visible = v;
    // *** TreeNodeTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    * <code>TreeNodeTreeModel</code> is an <code>AbstractTreeModel</code>
    * implementation for <code>javax.swing.tree.TreeNode</code> objects.
    public class TreeNodeTreeModel extends AbstractTreeModel {
         * Creates a new <code>TreeNodeTreeModel</code> object.
         * @param root the root node
         public TreeNodeTreeModel(TreeNode root) {
              super();
              setRoot(root);
         * Returns the parent of the child node.
         * @param node the child node
         * @return the parent or null if root
         public Object getParent(Object node) {
              if(node != getRoot() && (node instanceof TreeNode)) {
                   return ((TreeNode)node).getParent();
              return null;
         * Returns the child of parent at index index in the parent's child array.
         * @param parent the parent node
         * @param index the index
         * @return the child or null if no children
         public Object getChild(Object parent, int index) {
              if(parent instanceof TreeNode) {
                   return ((TreeNode)parent).getChildAt(index);
              return null;
         * Returns the number of children of parent.
         * @param parent the parent node
         * @return the child count
         public int getChildCount(Object parent) {
              if(parent instanceof TreeNode) {
                   return ((TreeNode)parent).getChildCount();
              return 0;
         * Returns the index of child in parent.
         * @param parent the parent node
         * @param child the child node
         * @return the index of the child node in the parent
         public int getIndexOfChild(Object parent, Object child) {
              if(parent instanceof TreeNode && child instanceof TreeNode) {
                   return ((TreeNode)parent).getIndex((TreeNode)child);
              return -1;
         * Returns true if node is a leaf.
         * @param node the node
         * @return true if the node is a leaf
         public boolean isLeaf(Object node) {
              if(node instanceof TreeNode) {
                   return ((TreeNode)node).isLeaf();
              return true;
         * Main method for testing.
         * @param args the command-line arguments
         public static void main(String[] args) {
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
              root.add(new DefaultMutableTreeNode("child_1"));
              DefaultMutableTreeNode c2 = new DefaultMutableTreeNode("child_2");
              c2.add(new DefaultMutableTreeNode("child_2_A"));
              c2.add(new DefaultMutableTreeNode("child_2_B"));
              root.add(c2);
              root.add(new DefaultMutableTreeNode("child_3"));
              root.add(new DefaultMutableTreeNode("child_4"));
              JTree tree = new JTree(new TreeNodeTreeModel(root));
              f.getContentPane().add(new JScrollPane(tree));
              f.pack();
              f.setSize(300, 500);
              f.show();
    // *** AbstractTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.text.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    public abstract class AbstractTreeModel implements TreeModel {
         * The list of tree model listeners.
         private Vector modelListeners = new Vector();
         * The root object of the tree.
         private Object root = null;
         * Basic no-op constructor.
         public AbstractTreeModel() {
         * Gets the root object of the tree.
         * @return the root object
         public Object getRoot() {
              return this.root;
         * Sets the root object of the tree.
         * @param r the root object
         protected void setRoot(Object r) {
              this.root = r;
         * Gets the path to the root node for the specified object.
         * @param node the root node
         * @return the path to the object or <CODE>null</CODE>
         public Object[] getPathToRoot(Object node) {
              return getPathToRoot(node, 0);
         * Gets the path to the root node for the specified object.
         * @param node the root node
         * @param i the current index
         * @return the path to the object or <CODE>null</CODE>
         private Object[] getPathToRoot(Object node, int i) {
              Object anode[];
              if(node == null) {
                   if(i == 0) {
                        return null;
                   anode = new Object[i];
              } else {
                   i++;
                   if(node == getRoot()) {
                        anode = new Object[i];
                   } else {
                        anode = getPathToRoot(getParent(node), i);
                   anode[anode.length - i] = node;
              return anode;
         * Gets the parent object of the specified object. This method is not
         * part of the <code>javax.swing.tree.TreeModel</code> interface, but is
         * required to support the <code>getPathToRoot(Object)</code> method,
         * which is widely used in this class. Therefore, it is important to
         * correctly implement this method.
         * @param obj the object
         * @parma the parent object or null if no parent or invalid object
         protected abstract Object getParent(Object obj);
         * Adds a listener for the <CODE>TreeModelEvent</CODE> posted after the
         * tree changes.
         * @param l the tree model listener
         public void addTreeModelListener(TreeModelListener l) {
              modelListeners.addElement(l);
         * Removes a listener previously added with addTreeModelListener().
         * @param l the tree model listener
         public void removeTreeModelListener(TreeModelListener l) {
              modelListeners.removeElement(l);
         * Forces the tree to reload. This is useful when many changes occur
         * under the root node in the tree structure.
         * <b>NOTE:</b> This will cause the tree to be collapsed. To maintain
         * the expanded nodes, see the <code>getExpandedPaths(JTree)</code>
         * and <code>expandPaths(JTree, ArrayList)</code> methods.
         * @see #getExpandedPaths(JTree)
         * @see #expandPaths(JTree, ArrayList)
         public void reload() {
              reload(getRoot());
         * Forces the tree to repaint. This is useful when many changes occur
         * under a specific node in the tree structure.
         * <b>NOTE:</b> This will cause the tree to be collapsed below the
         * updated node.
         * @param node the node that changed
         public void reload(Object node) {
              if(node != null) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   fireTreeStructureChanged(new TreeModelEvent(this, tp));
         * Messaged when the user has altered the value for the item identified
         * by <CODE>path</CODE> to <CODE>newValue</CODE>.
         * @param path the path to the changed object
         * @param newValue the new value
         public void valueForPathChanged(TreePath path, Object newValue) {
              nodeChanged(path.getLastPathComponent());
         * Notifies the tree that nodes were inserted. The index is looked up
         * automatically.
         * @param node the parent node
         * @param child the inserted child node
         public void nodeInserted(Object node, Object child) {
              nodeInserted(node, child, -1);
         * Notifies the tree that nodes were inserted.
         * @param node the parent node
         * @param child the inserted child node
         * @param index the index of the child
         public void nodeInserted(Object node, Object child, int index) {
              if(index < 0) {
                   index = getIndexOfChild(node, child);
              if(node != null && child != null && index >= 0) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   int[] ai = { index };
                   Object[] ac = { child };
                   fireTreeNodesInserted(new TreeModelEvent(this, tp, ai, ac));
         * Notifies the tree that nodes were removed. The index is required
         * since by this point, the object will no longer be in the tree.
         * @param node the parent node
         * @param child the removed child node
         * @param index the index of the child
         public void nodeRemoved(Object node, Object child, int index) {
              if(node != null && child != null && index >= 0) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   int[] ai = { index };
                   Object[] ac = { child };
                   fireTreeNodesRemoved(new TreeModelEvent(this, tp, ai, ac));
         * Notifies the tree that a node was changed.
         * @param node the changed node
         public void nodeChanged(Object node) {
              if(node != null) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   fireTreeNodesChanged(new TreeModelEvent(this, tp, null, null));
         * Fires "tree nodes changed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesChanged(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesChanged(event);
         * Fires "tree nodes inserted" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesInserted(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesInserted(event);
         * Fires "tree nodes removed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesRemoved(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesRemoved(event);
         * Fires "tree structure changed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeStructureChanged(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeStructureChanged(event);
         * Records the list of currently expanded paths in the specified tree.
         * This method is meant to be called before calling the
         * <code>reload()</code> methods to allow the tree to store the paths.
         * @param tree the tree
         * @param pathlist the list of expanded paths
         public ArrayList getExpandedPaths(JTree tree) {
              ArrayList expandedPaths = new ArrayList();
              addExpandedPaths(tree, tree.getPathForRow(0), expandedPaths);
              return expandedPaths;
         * Adds the expanded descendants of the specifed path in the specified
         * tree to the internal expanded list.
         * @param tree the tree
         * @param path the path
         * @param pathlist the list of expanded paths
         private void addExpandedPaths(JTree tree, TreePath path, ArrayList pathlist) {
              Enumeration enum = tree.getExpandedDescendants(path);
              while(enum.hasMoreElements()) {
                   TreePath tp = (TreePath)enum.nextElement();
                   pathlist.add(tp);
                   addExpandedPaths(tree, tp, pathlist);
         * Re-expands the expanded paths in the specified tree. This method is
         * meant to be called before calling the <code>reload()</code> methods
         * to allow the tree to store the paths.
         * @param tree the tree
         * @param pathlist the list of expanded paths
         public void expandPaths(JTree tree, ArrayList pathlist) {
              for(int i = 0; i < pathlist.size(); i++) {
                   tree.expandPath((TreePath)pathlist.get(i));

    Hey
    I'm not trying to show anyone up here, but having just built a tree model for displaying an XML document in a tree, I thought this seemed like a neat exercise.
    I implemented this very differently from the @OP. I only have one class, HiddenNodeTreeModel. All the hidden node data is stored in the model itself in my class. The advantage of what I've created is it will work with any TreeModel. The disadvantage is that I think it's not going to be very scalable - the additional computing to get the number of child nodes and to adjust indexes is heavy. So if you need a scalable solution definitely don't use this.
    Anyway here you go
    HiddenNodeTreeModel.java
    ======================
    package tjacobs.ui.tree;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JTree;
    import javax.swing.event.TreeModelListener;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeModel;
    import javax.swing.tree.TreePath;
    import tjacobs.ui.WindowUtilities;
    public class HiddenNodeTreeModel implements TreeModel {
         TreeModel mModel;
         ArrayList<Object> mHidden = new ArrayList<Object>();
         public HiddenNodeTreeModel (TreeModel model) {
              mModel = model;
         public void addTreeModelListener(TreeModelListener arg0) {
              mModel.addTreeModelListener(arg0);
         private ArrayList<Integer> getHiddenChildren(Object parent) {
              ArrayList<Integer> spots = new ArrayList<Integer>();
              Iterator _i = mHidden.iterator();
              while (_i.hasNext()) {
                   Object hidden = _i.next();
                   int idx = mModel.getIndexOfChild(parent, hidden);
                   if (idx != -1) {
                        spots.add(idx);
              return spots;
         public Object getChild(Object arg0, int index) {
              ArrayList<Integer> spots = getHiddenChildren(arg0);
              Collections.sort(spots);
              Iterator<Integer> _i = spots.iterator();
              while (_i.hasNext()) {
                   int num = _i.next();
                   if (num <= index) {
                        index++;
              return mModel.getChild(arg0, index);
         public int getChildCount(Object arg0) {
              ArrayList list = getHiddenChildren(arg0);
              System.out.println("size = " + list.size());
              return mModel.getChildCount(arg0) - list.size();
         public int getIndexOfChild(Object arg0, Object arg1) {
              int index = mModel.getIndexOfChild(arg0, arg1);
              ArrayList<Integer> spots = getHiddenChildren(arg0);
              Collections.sort(spots);
              Iterator<Integer> _i = spots.iterator();
              int toSub = 0;
              while (_i.hasNext()) {
                   int num = _i.next();
                   if (num <= index) {
                        toSub++;
              return index - toSub;
         public Object getRoot() {
              // TODO Auto-generated method stub
              return mModel.getRoot();
         public boolean isLeaf(Object arg0) {
              // TODO Auto-generated method stub
              return mModel.isLeaf(arg0);
         public void removeTreeModelListener(TreeModelListener arg0) {
              mModel.removeTreeModelListener(arg0);
         public void valueForPathChanged(TreePath arg0, Object arg1) {
              mModel.valueForPathChanged(arg0, arg1);
         public void hideNode(Object node) {
              if (node instanceof TreePath) {
                   node = ((TreePath)node).getLastPathComponent();
              mHidden.add(node);
         public void showNode(Object node) {
              mHidden.remove(node);
         public void showAll() {
              mHidden.clear();
          * @param args
         public static void main(String[] args) {
              // TODO Auto-generated method stub
              DefaultMutableTreeNode A = new DefaultMutableTreeNode("A");
              DefaultMutableTreeNode B = new DefaultMutableTreeNode("B");
              DefaultMutableTreeNode C = new DefaultMutableTreeNode("C");
              DefaultMutableTreeNode D = new DefaultMutableTreeNode("D");
              DefaultMutableTreeNode E = new DefaultMutableTreeNode("E");
              DefaultMutableTreeNode F = new DefaultMutableTreeNode("F");
              A.add(B);
              B.add(C);
              B.add(D);
              B.add(E);
              E.add(F);
              DefaultTreeModel model = new DefaultTreeModel(A);
              final HiddenNodeTreeModel hmodel = new HiddenNodeTreeModel(model);
              final JTree tree = new JTree(hmodel);
              JFrame jf = new JFrame("HiddenNodeTreeModel Test");
              jf.add(tree);
              JMenuBar bar = new JMenuBar();
              jf.setJMenuBar(bar);
              JMenu menu = new JMenu("Options");
              bar.add(menu);
              final JMenuItem hide = new JMenuItem("Hide");
              final JMenuItem show = new JMenuItem("ShowAll");
              menu.add(hide);
              menu.add(show);
              ActionListener al = new ActionListener() {
                   public void actionPerformed(ActionEvent ae) {
                        if (ae.getSource() == hide) {
                             hmodel.hideNode(tree.getSelectionPath());
                             tree.updateUI();
                        else {
                             hmodel.showAll();
                             tree.updateUI();
              hide.addActionListener(al);
              show.addActionListener(al);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              jf.setBounds(100,100,100,100);
              jf.setVisible(true);
    }

  • Small issue with custom table cell editor and unwanted table row selection

    I'm using a custom table cell editor to display a JTree. Thing i notice is that when i select a value in the tree pop-up, the pop-up closes (as it should) but then every table row, from the editing row to the row behind the pop-up when i selected the value becomes highlighted. I'm thinking this is a focus issue, but it thought i took care of that. To clairfy, look at this: Before . Notice how the "Straightening" tree item is roughly above the "Stock Thickness" table row? When i select Straightening, this is what happens to my table: After .
    My TreeComboBox component:
    public class TreeComboBox extends JPanel implements MouseListener {
        private JTextField itemField;
        private TreeModel treeModel;
        private ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();
        private Object selectedItem;
         * Creates a new <code>TreeComboBox</code> instance.
         * @param treeModel the tree model to be used in the drop-down selector.
        public TreeComboBox(TreeModel treeModel) {
            this(treeModel, null);
         * Creates a new <code>TreeComboBox</code> instance.
         * @param treeModel the tree model to be used in the drop-down selector.
         * @param selectedItem tree will expand and highlight this item.
        public TreeComboBox(TreeModel treeModel, Object selectedItem) {
            this.treeModel = treeModel;
            this.selectedItem = selectedItem;
            initComponents();
         * Returns the current drop-down tree model.
         * @return the current <code>TreeModel</code> instance.
        public TreeModel getTreeModel() {
            return treeModel;
         * Sets the tree model.
         * @param treeModel a <code>TreeModel</code> instance.
        public void setTreeModel(TreeModel treeModel) {
            this.treeModel = treeModel;
         * Returns the selected item from the drop-down selector.
         * @return the selected tree object.
        public Object getSelectedItem() {
            return selectedItem;
         * Sets the selected item in the drop-down selector.
         * @param selectedItem tree will expand and highlight this item.
        public void setSelectedItem(Object selectedItem) {
            this.selectedItem = selectedItem;
            String text = selectedItem != null ? selectedItem.toString() : "";
            itemField.setText(text);
            setToolTipText(text);
         * Overridden to enable/disable all child components.
         * @param enabled flat to enable or disable this component.
        public void setEnabled(boolean enabled) {
            itemField.setEnabled(enabled);
            super.setEnabled(enabled);
        public void addActionListener(ActionListener listener) {
            actionListeners.add(listener);
        public void removeActionListener(ActionListener listener) {
            actionListeners.remove(listener);
        // MouseListener implementation
        public void mouseClicked(MouseEvent e) {
        public void mouseEntered(MouseEvent e) {
        public void mouseExited(MouseEvent e) {
        public void mousePressed(MouseEvent e) {
        public void mouseReleased(MouseEvent e) {
            showPopup();
        private void initComponents() {
            setLayout(new GridBagLayout());
            itemField = new JTextField();
            itemField.setEditable(false);
            itemField.setText(selectedItem != null ? selectedItem.toString() : "");
            itemField.addMouseListener(this);
            add(itemField, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        private void showPopup() {
            final TreePopup popup = new TreePopup();
            final TreeComboBox tcb = this;
            final int x = itemField.getX();
            final int y = itemField.getY() + itemField.getHeight();
            int width = itemField.getWidth() + popupButton.getWidth();
            Dimension prefSize = popup.getPreferredSize();
            prefSize.width = width;
            popup.setPreferredSize(prefSize);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    popup.show(tcb, x, y);
                    popup.requestFocusInWindow();
        private void fireActionPerformed() {
            ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "TreeComboBoxSelection");
            for (ActionListener listener : actionListeners) {
                listener.actionPerformed(e);
        private class TreePopup extends JPopupMenu {
            private JTree tree;
            private JScrollPane scrollPane;
            public TreePopup() {
                initComponents();
                initData();
            private void initData() {
                if (treeModel != null) {
                    tree.setModel(treeModel);
            private void initComponents() {
                setFocusable(true);
                setFocusCycleRoot(true);
                tree = new JTree();
                tree.setRootVisible(false);
                tree.setShowsRootHandles(true);
                tree.setFocusable(true);
                tree.setFocusCycleRoot(true);
                tree.addTreeSelectionListener(new TreeSelectionListener() {
                    public void valueChanged(TreeSelectionEvent e) {
                        tree_valueChanged(e);
                scrollPane = new JScrollPane(tree);
                add(scrollPane);
            private void tree_valueChanged(TreeSelectionEvent e) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
                setSelectedItem(node.getUserObject());
                fireActionPerformed();
                this.setVisible(false);
    }My TreeComboBoxTableCellEditor:
    public class TreeComboBoxTableCellEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
        protected TreeComboBox treeComboBox;
        protected ArrayList<CellEditorListener> cellEditorListeners = new ArrayList<CellEditorListener>();
        public TreeComboBoxTableCellEditor(TreeComboBox treeComboBox) {
            this.treeComboBox = treeComboBox;
            treeComboBox.addActionListener(this);
        public Object getCellEditorValue() {
            return treeComboBox.getSelectedItem();
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            treeComboBox.setSelectedItem(value);
            return treeComboBox;
        public void actionPerformed(ActionEvent e) {
            stopCellEditing();
    }Any thoughts?
    Edited by: MiseryMachine on Apr 3, 2008 1:21 PM
    Edited by: MiseryMachine on Apr 3, 2008 1:27 PM

    As I said, you have to have empty context elements before additional rows will be open for input.
    For instance if you want to start with 5 rows available for input do the following to your internal table that you will bind:
    data itab type standard table of sflight.
    do 5 times.
      append initial line to itab.
    enddo.
    context_node->bind_table( itab ).
    The other option if you need n number of rows is to add a button to the table toolbar for adding more rows. When this button is pressed, you add a new context element to the node - thereby creating a new empty row in the table.

  • How to get the root node of a tree?

    I wanna get all the leaf node of a tree.But JTree have no method about how to get the root TreeNode of a tree.Then how should I do?

    try this:
    http://javaalmanac.com/egs/javax.swing.tree/GetNodes.html?l=rel

  • DefaultTreeCellRenderer & LookAndFeel UI

    Hi All,
    I need HELP!!!
    I've found small bug in DefaultTreeCellRenderer Class and Look&Feel UserInterface.
    After use DefaultTreeCellRenderer for JTree, SwingUtilities.updateComponentTreeUI() method can't change UI for initialised JTrees. For new created Trees all work properly.
    The next small Application show this:
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.UIManager.*;
    import java.awt.*;
    import java.awt.event.*;
    public class TreeRendererBug extends javax.swing.JFrame {
        static private boolean DEBUG = true;
        static private LookAndFeelInfo style[];
        private javax.swing.JMenu myMenuStyle = new javax.swing.JMenu();
        private ButtonGroup groupStyleMenu = new ButtonGroup();
        private javax.swing.JMenuBar jMenuBar1 = new javax.swing.JMenuBar();
        private javax.swing.JMenu jMenu1;
        private javax.swing.JPanel jPanel1 = new javax.swing.JPanel();
        private javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
        private javax.swing.JTree jTree1 = new javax.swing.JTree();
        public TreeRendererBug() {
            try {
                LookAndFeel curStyle=  UIManager.getLookAndFeel();
                style = javax.swing.UIManager.getInstalledLookAndFeels();
                if(style != null) {
                    RadioMenuListener myRadioMenuListener = new RadioMenuListener();
                    for(int ii=0; ii< style.length ;ii++) {
                        if(DEBUG) System.out.println(style[ii].getClassName());
                        JRadioButtonMenuItem jRadioMenuItem = new javax.swing.JRadioButtonMenuItem(style[ii].getName(),style[ii].getName()==curStyle.getName());
                        jRadioMenuItem.setActionCommand(style[ii].getClassName());
                        jRadioMenuItem.addActionListener(myRadioMenuListener);
                        groupStyleMenu.add(jRadioMenuItem);
                        myMenuStyle.add(jRadioMenuItem);
            } catch (Exception e) {
                System.out.println("ERROR: "+e.toString());
            jMenu1 = myMenuStyle;
            jMenu1.setText("UI Style");
            jMenuBar1.add(jMenu1);
            jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, 0));
            jScrollPane1.setViewportView(jTree1);
            jPanel1.add(jScrollPane1);
            getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
            setJMenuBar(jMenuBar1);
            // !!!!!!  Bug in DefaultTreeCellRenderer !!!!!!!!
            // after comment this row, L&F will be set UI style to the all JTree elements
            jTree1.setCellRenderer(new DefaultTreeCellRenderer());
            addWindowListener(new java.awt.event.WindowAdapter() {
                public void windowClosing(java.awt.event.WindowEvent evt) {
                    System.exit (0); }
            pack ();
        public static void main (String args[]) {
            new TreeRendererBug ().show ();
        class RadioMenuListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                if(DEBUG) System.out.println("Command "+ e.getActionCommand() );
                try {
                    UIManager.setLookAndFeel(e.getActionCommand());
                    SwingUtilities.updateComponentTreeUI(TreeRendererBug.this);
                    TreeRendererBug.this.validate();
                } catch (Exception exc) {
                    System.out.println("ERROR: "+exc.toString());
    How change UI for initialised JTree with DefaultTreeCellRenderer ?
    Thank you in advance,
    AT.

    Hi All,
    I need HELP!!!
    I've help my self ! :))))
    after change style is it is necessary set new CellRenderer for JTree:
        class RadioMenuListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                if(DEBUG) System.out.println("Command "+ e.getActionCommand() );
                try {
                    UIManager.setLookAndFeel(e.getActionCommand());
                    SwingUtilities.updateComponentTreeUI(TreeRendererBug.this);
                    jTree1.setCellRenderer(new DefaultTreeCellRenderer());
                    TreeRendererBug.this.validate();
                } catch (Exception exc) {
                    System.out.println("ERROR: "+exc.toString());
    [//code]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • Tracing Directory Tree Structure !

    I am trying to make a program which read all directories and each one's respective subdirectories, along with files in a disk. Can I use concept of recursion, to trace a directory and it's subdirectory till a subdirectory with no child directory is encountered. Could you please help me to implement this problem in code.
    Regards

    hi,
    sure you have to use a recursive algorithm! Try the following:
    public void initTree(){
    DefaultTreeModel model=new DefaultTreeModel(getNodeForFolder(File.listRoots()[0])); //the starting point, you may choose sth. else
    JTree tree=new JTree(model);
    //recursive method
    private TreeNode getNodeForFolder(File folder){
    DefaultMutableTreeNode node=new DefaultMutableTreeNode(folder);
    File[] children=folder.listFiles();
    for(int i=0;i<children.length;i++){
      if(children.isDirectory())node.addChild(getNodeForFolder(children[i]));
    else node.addChild(new DefaultMutableTreeNode(children[i]));
    best regards, Michael

  • What does removeFromParent() exactly do?

    Hello,
    Can anyone tell me what the method removeFromParent() of the class
    DefaultMutableTreeNode do?
    Does it delete the node along with its children?
    Or
    Does it delete only the child nodes and gives the node a null parent?
    Thank u.

    TreeNode is the interface that the nodes implement, not the tree itself.
    (An apple is different from an apple tree!)
    You must have a TreeModel object floating around somewhere. For
    instance, JTree has the method:
    public TreeModel getModel()And unless you defined your own custom tree model, that TreeModel
    will actually be an instance of DefaultTreeModel.

Maybe you are looking for

  • Not authorized  in the Enterprise Portal

    Hi, I have a problem setting up the portal. When browsing to the User Administration tab I get: "You are not authorized to access this application; contact your system administrator". I'm logged on as J2EE_ADMIN. Should I log on as another user? Is t

  • Address Book Question -- IS THIS POSSIBLE ??

    Is "appending" information possible to address book ? Or like a way to add info from one address book to another with out it deleting anything on the one getting updated OR with out making duplicates of the contact info(s) ???? Kinda like what we cal

  • Scanning lots of photos - ideas?

    I'm looking to scan a ton of old family photos. One scanner, the Kodak i1210, got a great write-up in the WSJ in early January. Here is a Consumer Reports blog post on it (I don't think he's right about it not being available to consumers): http://bl

  • Incorrect constant pool entry count

    Hi , I found with this simple class , the class file has incorrect constant pool count, public class Smpl public final long j = 0;           class file dumped is : 0xCA 0xFE 0xBA 0xBE 0x00 0x00 0x00 0x32 0x00 {color:#ff0000}0x14 <- pool count is 0x14

  • IMessage crashes my computer. I have to disable it to do anything

    for some reason my whole system crashes if I enable iMessage or face time on my iMac and Mac book pro. Its fine on my iPhone and iPad. I would love to use this service but it completely disables my system. After many hours of testing and trouble shoo