需要根据用户输入添加和删除TreeNodes。实际上,除了移除节点有时会导致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__,但我想知道根本原因)
编辑
用户输入是一种过滤模式,根据这种模式,需要完全删除一些二级根节点。单个剩余的第二级根节点的子节点正在被过滤。
private synchronized static void reloadTree(final JTree tree,final VAFilteredTreeModel treeModel)public void removeApplicationElementNodes(List<String> appElemNodeTypesToKeepAlive)私有同步静态空reloadTree(最终JTree树,最终MVAFilteredTreeModel treeModel){
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);
}
}
}
}为了过滤节点,我重写了getChild和DefaultTreeModel的getChildCount方法。
@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吗?
发布于 2014-05-02 16:58:37
最近我解决了这个问题。问题是这种方法:
private synchronized static void reloadTree(final JTree tree, final MVAFilteredTreeModel treeModel)
是在它自己的线程中执行的,该线程与EDT相连。解决方案是将此方法调用移动到SwingWorker实例中,以便节点的呈现由EDT完成。
https://stackoverflow.com/questions/23090470
复制相似问题