JTree';DefaultTreeModel.removeNodeFromParent()';导致';java.lang.ArrayIndexOutOfBoundsException';

JTree';DefaultTreeModel.removeNodeFromParent()';导致';java.lang.ArrayIndexOutOfBoundsException';,java,swing,jtree,treenode,Java,Swing,Jtree,Treenode,Java应用程序需要根据用户输入添加和删除TreeNode。实际上,除了删除节点有时会导致出现ArrayIndexOutOfBoundsException之外,一切都正常。我要做的是首先确定是否应该显示节点。虽然第一种情况不会改变任何东西,但第二种情况将从其父节点中删除节点 removeNodeFromParent(treeNode) 不幸的是,有时会将以下例外情况打印到控制台,例如:1>=1可能不同,例如177>=177或177>=98 Exception in thread "AWT-Eve

Java应用程序需要根据用户输入添加和删除TreeNode。实际上,除了删除节点有时会导致出现
ArrayIndexOutOfBoundsException
之外,一切都正常。我要做的是首先确定是否应该显示节点。虽然第一种情况不会改变任何东西,但第二种情况将从其父节点中删除节点

removeNodeFromParent(treeNode)

不幸的是,有时会将以下例外情况打印到控制台,例如:
1>=1
可能不同,例如
177>=177
177>=98

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
    at java.util.Vector.elementAt(Unknown Source)
    at javax.swing.tree.DefaultMutableTreeNode.getChildAt(Unknown Source)
    at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.nextElement(Unknown Source)
    at javax.swing.tree.VariableHeightLayoutCache$VisibleTreeStateNodeEnumeration.nextElement(Unknown Source)
    at javax.swing.plaf.basic.BasicTreeUI.paint(Unknown Source)
    at javax.swing.plaf.ComponentUI.update(Unknown Source)
    at javax.swing.JComponent.paintComponent(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JViewport.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent._paintImmediately(Unknown Source)
    at javax.swing.JComponent.paintImmediately(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$700(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
有没有办法避免这种行为

(我知道有一个
DefaultUncaughtExceptionHandler
,用于隐藏这样的堆栈跟踪,但我想知道根本原因)


[编辑]

用户输入是一种过滤模式,根据该模式,需要完全删除一些第二级根节点。剩余的单个第二级根节点的子节点将被筛选

  • 用户插入过滤器模式
  • 应用筛选器本身:
    专用同步静态void重载树(最终JTree树、最终VAFilteredTreeModel树模型)
  • 删除不需要的二级根节点
    公共void removeApplicationElementNodes(列出AppElementNodeTypesTokeAppAlive)
  • 私有同步静态void重载树(最终JTree树, 最终MVAFilteredTreeModel){


    有什么办法可以避免上面的运行时异常吗?

    最近我解决了这个问题。问题是方法:

    private synchronized static void reloadTree(最终JTree树、最终MVAFilteredTreeModel树模型)


    在EDT自身的线程appart中执行。解决方案是将此方法调用移动到一个
    SwingWorker
    实例中,以便节点的呈现由EDT完成。

    如果您希望我们调试您的代码,我们将需要查看您的代码。异常非常简单,因此可以避免这种行为从不访问不存在的数组元素开始。我感觉您使用的是>=(或@takendark Thx,source)added@derstrom8我从未使用过>=或
            TreePath selectedTP = tree.getSelectionPath();
    
            MVAFilteredTree filteredTree = (MVAFilteredTree) tree;
            List<String> visibleNodeNames = new Vector<String>(
                    filteredTree
                            .getTreeFilter()
                            .getRecentlyAppliedPositiveMVAApplicationElementFilterNodeNames());
            for (String nodeName : visibleNodeNames) {
                TreePath path = treeModel.getPathToNode(nodeName);
                if (path != null) {
                    treeModel.reloadTreeNode(nodeName);
                    tree.expandPath(path);
                    tree.setSelectionPath(path);
    
                    if(selectedTP == null){
                        selectedTP = path;
                    }
                }
            }
    
            /*
             * If the there's still no selected node, then get the path of any
             * available node 2nd level root node
             */
            if (selectedTP == null) {
                MVANode aoTestNode = Plugins.getInstance().getNodeFromTreeNodeContainer();
                if (aoTestNode != null) {
                    selectedTP = MVATreeUtil.getTreePath(aoTestNode);
                    tree.expandPath(selectedTP);
                }
            }
    
            AbstractAddon addon = AddonProvider.getInstance().getActiveAddon();
            if (addon.isActive() && addon.expandAllTreeNodes()) {
                MVATreeUtil.expandAllTreeNodes(filteredTree);
            } else {
                MVATreeUtil
                        .expandAllTreeNodesAccordingToTheAppliedFilters(filteredTree);
                tree.scrollPathToVisible(treeModel.getPathToNode(treeModel
                        .getRootNode().getName()));
            }
    
            TreePath visibleTreePath = MVATreeUtil.getNextVisibleTreePath(
                    filteredTree, selectedTP);
    
            if(visibleTreePath != null){
                tree.setSelectionPath(visibleTreePath);
                tree.scrollPathToVisible(visibleTreePath);
            }
        }
    
    
    public void removeApplicationElementNodes(
            List<String> appElemNodeTypesToKeepAlive) {
        for (String nodeType : Plugins.getInstance()
                .getPluggedInApplicationElementTreeNodeTypes()) {
            if (!appElemNodeTypesToKeepAlive.contains(nodeType)) {
                MVANode mvaNode = Plugins.getInstance()
                        .getApplicationElementNodes().get(nodeType);
                if (mvaNode!= null && MVATreeUtil.checkNodeExists(getRootNode(),
                        mvaNode.getName())) {
                    removeNodeFromParent(mvaNode);
                }
            }
        }
    }
    
    @Override
    public Object getChild(Object parent, int index) {
        int count = 0;
        int childCount = super.getChildCount(parent);
        for (int i = 0; i < childCount; i++) {
            /*
             * In case that the child count has changed during iteration, return
             * null
             */
            if (super.getChildCount(parent) != childCount) {
                return null;
            }
            Object child = super.getChild(parent, i);
            if (getTreeFilter().isTreeNodeFiltered(child)) {
                if (count == index) {
                    return child;
                }
                count++;
            }
        }
        /*
         * return an pseudo node in case that there isn't any real node at that
         * index. This can happen due to node collapses and node filtering.
         */
        return new DefaultMutableTreeNode();
    }
    
    @Override
    public int getChildCount(Object parent) {
        int count = 0;
        int childCount = super.getChildCount(parent);
        for (int i = 0; i < childCount; i++) {
            /*
             * in case that the child count changed during iteration, return
             * with -1
             */
            if (super.getChildCount(parent) != childCount) {
                return -1;
            }
            Object node = super.getChild(parent, i);
            if (getTreeFilter().isTreeNodeFiltered(node)) {
                count++;
            }
        }
        return count;
    }