在重定位JTree中的节点时,Swing会抛出ArrayIndexOutOfBoundsException

时间:2018-01-02 11:12:08

标签: java swing indexoutofboundsexception jtree defaulttreemodel

我想更改JTree中某些节点的位置。这是代码:

public void changeNodePositionInTree() {
   DefaultTreeModel model = (DefaultTreeModel)tree.getModel();

   for(int i = 0; i < someList.size(); i++) {
      DefaultMutableTreeNode node = findNodeInTreeByName(someList.get(i));

      //if node is in a tree, then change its location and insert it in position i
      if(node != null) {
         model.removeNodeFromParent(node);
         model.insertNodeInto(node, tree.getRoot(), i);
      }
   }
}

SwingUtilities.invokeLater(new Runnable() {
   public void run() {
      changeNodePositionInTree();
   }
});

我在使用此代码时面临两个问题:

  1. 有时很少有节点没有显示其文本,并且在末尾用一些截断和点(...)表示。
  2. 有时候我会得到这个JRE例外而且我不明白为什么。我认为它被抛出,因为我删除了一个节点,然后再次插入它,JRE尝试在这两个操作之前或之间重新绘制这个树。我怎么能避免这种情况?

      Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 22 >= 22
        at java.util.Vector.elementAt(Vector.java:474)
        at javax.swing.tree.DefaultMutableTreeNode.getChildAt(DefaultMutableTreeNode.java:245)
        at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.nextElement(VariableHeightLayoutCache.java:1695)
        at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.nextElement(VariableHeightLayoutCache.java:1653)
        at javax.swing.plaf.basic.BasicTreeUI.paint(BasicTreeUI.java:1183)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
        at javax.swing.JComponent.paintComponent(JComponent.java:780)
        at javax.swing.JComponent.paint(JComponent.java:1056)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JViewport.paint(JViewport.java:728)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1047)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paint(JComponent.java:1065)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
        at javax.swing.JComponent.paintChildren(JComponent.java:889)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
        at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
        at javax.swing.JComponent.paint(JComponent.java:1042)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
        at java.awt.Container.paint(Container.java:1975)
        at java.awt.Window.paint(Window.java:3912)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
        at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
        at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
        at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
        at java.awt.EventQueue.access$500(EventQueue.java:97)
        at java.awt.EventQueue$3.run(EventQueue.java:709)
        at java.awt.EventQueue$3.run(EventQueue.java:703)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    

1 个答案:

答案 0 :(得分:0)

不要在模型上使用insertNodeInto方法而是在根节点上调用add,最后在传递根节点的模型上调用nodesChanged方法。代码如下所示。

public void changeNodePositionInTree() {
   DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
   DefaultMutableTreeNode root = ( DefaultMutableTreeNode ) tree.getRoot();
   for(int i = 0; i < someList.size(); i++) {
      DefaultMutableTreeNode node = findNodeInTreeByName(someList.get(i));

      //if node is in a tree, then change its location and insert it in position i
      if(node != null) {
         model.removeNodeFromParent(node);
         root.add( node );
      }
   }

   // inform node that the root node got changed
   model.nodeChanged(root);

}

SwingUtilities.invokeLater(new Runnable() {
   public void run() {
      changeNodePositionInTree();
   }
});