Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

JTree expand problem

Posted on 2004-08-04
14
Medium Priority
?
1,487 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
Build and deliver software with DevOps

A digital transformation requires faster time to market, shorter software development lifecycles, and the ability to adapt rapidly to changing customer demands. DevOps provides the solution.

 
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 375 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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
Suggested Courses

715 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