2014-04-15 5 views
0

Java 응용 프로그램은 사용자 입력에 따라 TreeNode를 추가하고 제거해야합니다. 실제로 노드를 제거하면 가끔 ArrayIndexOutOfBoundsException이 발생한다는 것을 제외하고는 모든 것이 잘 작동합니다. 내가하고있는 일은 먼저 노드를 표시할지 여부를 결정하는 것입니다. 첫 번째 경우에는 아무 것도 변경되지 않지만 두 번째 경우에는 부모 노드가 제거됩니다. 1 >= 1 달라도 좋고 예 :JTree 'DefaultTreeModel.removeNodeFromParent()'가 'java.lang.ArrayIndexOutOfBoundsException'을 발생시킵니다.

removeNodeFromParent(treeNode);

불행히도 같은 식 wherby 다음 excetpion가 콘솔에 프린트한다 somtimes 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에 대해 알고 있어요,하지만 난 근본 원인을 알고 싶어)


[편집]

사용자를 입력은 일부 2 차 레벨 루트 노드를 완전히 제거해야하는 필터 패턴입니다. 남은 두 번째 레벨 루트 노드의 하위 노드가 필터링됩니다.private synchronized static void reloadTree(final JTree tree,final VAFilteredTreeModel treeModel)

  • 제거하지 필요한 2 수준 루트 노드public void removeApplicationElementNodes(List<String> appElemNodeTypesToKeepAlive)
  • 개인 동기화 정적 무효 :

    1. 사용자 적용 필터 자체 필터 패턴
    2. 를 삽입 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 내가 위의들이 RuntimeException을 피할 수있는 방법 DefaultTreeModel

      @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; 
      } 
      

      모든 아이디어의 getChildCount?

    +2

    코드를 디버그하려면 코드를 참조해야합니다. 예외는 꽤 자명하다. 그래서 동작을 피하는 것은 존재하지 않는 배열 요소에 접근하지 않는 것으로 시작한다. – csmckelvey

    +0

    > 또는 <를 사용할 때> = (또는 <=)을 사용하고 있다는 느낌이 들었습니다. – DerStrom8

    +0

    @Takendarkk Thx, 소스 추가 –

    답변

    0

    최근에이 문제가 해결되었습니다. 문제는 방법이었다 :

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

    은 EDT 아파트 자체 스레드 내에서 실행되었다. 해결 방법은 노드의 렌더링이 EDT에 의해 수행되도록 SwingWorker 인스턴스로이 메서드 호출을 이동하는 것이 었습니다.