Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

JTree:treeNodesRemoved throws ArrayIndexOutOfBoundsException

843806Sep 3 2008 — edited Sep 4 2008
Hi, I have a strange problem. I googled/searched the forums and found several entries - but no solution (it is not a threading problem).
I think I am missing something obvious...

Okay, here is a test case that fails:
import junit.framework.TestCase;

import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
public class TreeProblem extends TestCase {

  public void testSmallTest() throws InvocationTargetException, InterruptedException {
    //Just to ensure that threading is *not* a problem...
    SwingUtilities.invokeAndWait( new Runnable() {
      public void run() {
        MyTreeModel model = new MyTreeModel();
        JTree tree = new JTree( model );
        assertEquals( 21, tree.getRowCount() );

        model.removeIt(); //throws the exception thrown....

        assertEquals( 19, model.children.size() );
      }
    } );
  }

  /**
   * A simple model with just 20 children
   */
  private static class MyTreeModel implements TreeModel {
    private static final String ROOT = "root";

    private List<String> children = new ArrayList<String>();

    private MyTreeModel() {
      for ( int i = 0; i < 20; i++ ) {
        children.add( String.valueOf( i ) );
      }
    }

    public Object getRoot() {
      return ROOT;
    }

    public Object getChild( Object parent, int index ) {
      assertSame( ROOT, parent );
      return children.get( index );
    }

    public int getChildCount( Object parent ) {
      return children.size();
    }

    public boolean isLeaf( Object node ) {
      return node != ROOT;
    }

    public void valueForPathChanged( TreePath path, Object newValue ) {
      throw new UnsupportedOperationException();
    }

    public int getIndexOfChild( Object parent, Object child ) {
      return children.indexOf( child );
    }

    private final List<TreeModelListener> listeners = new ArrayList<TreeModelListener>();

    public void addTreeModelListener( TreeModelListener l ) {
      listeners.add( l );
    }

    public void removeTreeModelListener( TreeModelListener l ) {
      throw new UnsupportedOperationException();
    }

    /**
     * This method has everything hardcoded (only for testing purposes). Call only once...
     */
    public void removeIt() {
      assertEquals( 20, children.size() );

      //Remove the last two entries...
      Object[] removed = new Object[2];
      removed[0] = children.remove( 19 );
      removed[1] = children.remove( 18 );
      assertEquals( 18, children.size() );

      int[] indicies = new int[]{19, 18};

      for ( TreeModelListener listener : listeners ) {
        listener.treeNodesRemoved( new TreeModelEvent( this, new TreePath( ROOT ), indicies, removed ) );
      }
    }
  }
}
This code throws the following exception:
Caused by: java.lang.ArrayIndexOutOfBoundsException: 19 >= 19
	at java.util.Vector.elementAt(Vector.java:432)
	at javax.swing.tree.DefaultMutableTreeNode.getChildAt(DefaultMutableTreeNode.java:230)
	at javax.swing.tree.VariableHeightLayoutCache.treeNodesRemoved(VariableHeightLayoutCache.java:543)
	at javax.swing.plaf.basic.BasicTreeUI$Handler.treeNodesRemoved(BasicTreeUI.java:3707)
	at de.avat.jview.diary.model.TreeProblem$MyTreeModel.removeIt(TreeProblem.java:99)
	at de.avat.jview.diary.model.TreeProblem$1.run(TreeProblem.java:28)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Oct 2 2008
Added on Sep 3 2008
4 comments
272 views