首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JTree 'DefaultTreeModel.removeNodeFromParent()‘导致'java.lang.ArrayIndexOutOfBoundsException’

JTree 'DefaultTreeModel.removeNodeFromParent()‘导致'java.lang.ArrayIndexOutOfBoundsException’
EN

Stack Overflow用户
提问于 2014-04-15 17:24:32
回答 1查看 1.1K关注 0票数 0

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

removeNodeFromParent(treeNode);

不幸的是,有时会在控制台上打印以下超像素,比如:1 >= 1可能不同,例如177 >= 177177 >= 98

代码语言:javascript
复制
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__,但我想知道根本原因)

编辑

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

  1. 用户插入筛选模式。
  2. 应用过滤器本身: private synchronized static void reloadTree(final JTree tree,final VAFilteredTreeModel treeModel)
  3. 删除不需要的二级根节点 public void removeApplicationElementNodes(List<String> appElemNodeTypesToKeepAlive)

私有同步静态空reloadTree(最终JTree树,最终MVAFilteredTreeModel treeModel){

代码语言:javascript
复制
        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);
            }
        }
    }
}

为了过滤节点,我重写了getChildDefaultTreeModelgetChildCount方法。

代码语言:javascript
复制
@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;
}

有什么办法可以避免上述RuntimeExceptions吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-02 16:58:37

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

private synchronized static void reloadTree(final JTree tree, final MVAFilteredTreeModel treeModel)

是在它自己的线程中执行的,该线程与EDT相连。解决方案是将此方法调用移动到SwingWorker实例中,以便节点的呈现由EDT完成。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23090470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档