Solved

JTree expand problem

Posted on 2004-08-04
14
1,478 Views
Last Modified: 2009-07-29
I am trying to expand a tree path after a node is added, only if this is the only child node. However, I am running into the following sporadic problem:


java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
      at java.util.Vector.elementAt(Vector.java:427)
      at javax.swing.tree.DefaultMutableTreeNode.getChildAt(DefaultMutableTreeNode.java:230)
      at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.updateNextIndex(VariableHeightLayoutCache.java:1739)
      at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.updateNextObject(VariableHeightLayoutCache.java:1690)
      at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.nextElement(VariableHeightLayoutCache.java:1681)
      at javax.swing.plaf.basic.BasicTreeUI.paint(BasicTreeUI.java:1121)      
                at javax.swing.plaf.metal.MetalTreeUI.paint(MetalTreeUI.java:143)
      at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
      at javax.swing.JComponent.paintComponent(JComponent.java:541)
      at javax.swing.JComponent.paint(JComponent.java:808)
      at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4771)
      at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4724)
      at javax.swing.JComponent._paintImmediately(JComponent.java:4668)
      at javax.swing.JComponent.paintImmediately(JComponent.java:4477)
      at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:410)
      at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:117)
      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)
      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)


The code I am using to insert a node is:

      DefaultMutableTreeNode client = new DefaultMutableTreeNode( clientName );

      treeModel.insertNodeInto( client, onlineRoot, onlineRoot.getChildCount() );

      // if this is the first client added, initially expand this node
      if ( onlineRoot.getChildCount() == 1 ) {
          tree.expandRow( tree.getRowForPath( new TreePath( onlineRoot.getPath() ) ) );
          //tree.fireTreeExpanded( new TreePath( onlineRoot.getPath() ) );
      } // end if

      // notify the tree that this client has been added so it is rendered
      // properly
      notifyNodeChanged( clientName );


The call to notifyNodeChanged( clientName ) is used to fix a weird problem that occured sporadically as well - which was basically making a single node very large, requiring scrollbars to be displayed. It goes through the tree to find the corresponding node and calls a nodeChanged( node ) on it. I guess all I really need to do there (if in fact it helps) is just call treeModel.nodeChanged( client ).

Thanks!
0
Comment
Question by:ctjoumas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 4
14 Comments
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 11719315
if(vector.size()>0)
{
   //do your works
}
0
 

Author Comment

by:ctjoumas
ID: 11719366
I don't have a vector that stores anything.  I have a dynamic multilevel tree and want to expand a given level only if it's first child was just inserted.
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 11719447
if (onlineRoot.getChildCount()>0)
{
if ( onlineRoot.getChildCount() == 1 ) {
          tree.expandRow( tree.getRowForPath( new TreePath( onlineRoot.getPath() ) ) );
          //tree.fireTreeExpanded( new TreePath( onlineRoot.getPath() ) );
      } // end if
}
0
MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 11719471
if (onlineRoot.getChildCount()>0)
{
if ( onlineRoot.getChildCount() == 1 ) {
if (onlineRoot.getPath()!= null && onlineRoot.getPath().length>0)
{
          tree.expandRow( tree.getRowForPath( new TreePath( onlineRoot.getPath() ) ) );
          //tree.fireTreeExpanded( new TreePath( onlineRoot.getPath() ) );
      } // end if
}
}
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 11719697
This might be useful to expand ur tree node

// If expand is true, expands all nodes in the tree.
    // Otherwise, collapses all nodes in the tree.
    public void expandAll(JTree tree, boolean expand) {
        TreeNode root = (TreeNode)tree.getModel().getRoot();
   
        // Traverse tree from root
        expandAll(tree, new TreePath(root), expand);
    }
    private void expandAll(JTree tree, TreePath parent, boolean expand) {
        // Traverse children
        TreeNode node = (TreeNode)parent.getLastPathComponent();
        if (node.getChildCount() >= 0) {
            for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode)e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandAll(tree, path, expand);
            }
        }
   
        // Expansion or collapse must be done bottom-up
        if (expand) {
            tree.expandPath(parent);
        } else {
            tree.collapsePath(parent);
        }

Regards
Sudhakar
0
 
LVL 92

Accepted Solution

by:
objects earned 125 total points
ID: 11721955
Is the above code being called from the event dispatch thread?
If not then it should be.

>  notifyNodeChanged( clientName );

that shouldn't be necessary
0
 

Author Comment

by:ctjoumas
ID: 11724833
sudhakar_koundinya: Except for your last post, that seems pretty much what I already have.

objects:

> Is the above code being called from the event dispatch thread?

I assume you are asking about my code?  If so, how do I call it from the event dispatch thread?  The code to add the node is called when a node is requested to be added, and the expansion of the row is called in the same method only if the node just added is the only child for the row.

So, I guess that means it is not in the event dispatch thread.  How do I do that?  I think I had tried using an invokeLater method, but that didn't work and I'm assuming that isn't quite the same thing.

as for the notifyNodeChanged( clientName ); line, all that does is basically:
treeModel.nodeChanged( node ); where node is the node of the clientName.  It seemed to fix my problem, but hte problem that I was seeing (where if there was only one node added it would take up the entire height of the tree and require scrollbars) occured once every 20 times or so.
0
 

Author Comment

by:ctjoumas
ID: 11724859
objects: btw, I just changed it to this - let me know what you think.  I still need to test it to see if I can run into the problem again:

        Runnable expandTree = new Runnable() {
            public void run() {
                tree.expandRow( tree.getRowForPath( new TreePath( offlineRoot.getPath() ) ) );
            }
        };

        // if this is the first client added, initially expand this node
        if ( offlineRoot.getChildCount() == 1 ) {
            SwingUtilities.invokeLater( expandTree );
        } // end if
0
 

Author Comment

by:ctjoumas
ID: 11728474
Hmm...objects, are you saying to put all of ny code in an event dispatch thread?  It seems to work, but it is always hard to prove.  I am sending notifications to other windows when adding or removing a node, so I guess all of that can be put into the event dispatch thread too?

My other question is - should only the expandRow be in an event dispatch thread, or should treeModel.removeNodeFromParent( node ) (and other calls) also be in one?

Thanks!
0
 
LVL 92

Expert Comment

by:objects
ID: 11731420
> are you saying to put all of ny code in an event dispatch thread?

all code that updates the gui

> should only the expandRow be in an event dispatch thread, or should treeModel.removeNodeFromParent( node ) (and other calls) also be in one?

yes
0
 

Author Comment

by:ctjoumas
ID: 11734400
> all code that updates the gui

So, in the case of
    DefaultMutableTreeNode client = new DefaultMutableTreeNode( clientName );

    treeModel.insertNodeInto( client, offlineRoot, offlineRoot.getChildCount() );

    if ( offlineRoot.getChildCount() == 1 )
        tree.expandRow( tree.getRowForPath( new TreePath( offlineRoot.getPath() ) ) );

should, only the expandRow be in there?  Or does insertNodeInto also update the gui?


> > should only the expandRow be in an event dispatch thread, or should treeModel.removeNodeFromParent( node ) (and other calls) also be in one?

> yes

Are you saying yes to the first or second part of that question? :)
0
 
LVL 92

Expert Comment

by:objects
ID: 11740602
>  Or does insertNodeInto also update the gui?

If the model is being displayed then yes it does.

> Are you saying yes to the first or second part of that question? :)

both :)
0
 

Author Comment

by:ctjoumas
ID: 11754178
Thanks!
0
 
LVL 92

Expert Comment

by:objects
ID: 11758554
0

Featured Post

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Suggested Courses

632 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question