Swing генерирует ArrayIndexOutOfBoundsException при перемещении узлов в JTree
Я хочу изменить расположение некоторых узлов в моем 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();
}
});
Я сталкиваюсь с двумя проблемами с этим кодом:
- Иногда немногие узлы не отображают полный текст, и он представлен с некоторым усечением и точками (...) в конце.
Иногда я получаю это исключение 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 ответ
Не используйте метод insertNodeInto для модели, вместо этого вызовите add для корневого узла и, наконец, вызовите метод nodeChanged для модели, передавая корневой узел. Код ниже для вашей справки.
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();
}
});