2016-08-26 2 views
0

Я создал программу, которая принимает несколько входов от пользователя через текстовое поле и кнопку и диалог с файлом и форматирует их в дерево SWT, в котором пользователь можно выбрать через флажки свои элементы.Java SWT Tree TreeItem Listener возвращает ошибку удаления исключенного виджета

Проблема, с которой я сталкиваюсь, заключается в том, что я хочу, чтобы она обновлялась в реальном времени для пользователя, и я нашел решение на этом форуме об использовании метода layout() контейнера и работает с моим деревом, но только если я назову dispose() на этом дереве, а затем перестраиваю его/перерисовывая его потом.

За этим деревом у меня есть структура данных дерева, которую я использую для управления всеми данными. Кроме того, класс, который я использую, реализует интерфейс SWT Dialog, так что, когда я нажимаю кнопку, появится окно с областью ввода дерева и текста.

Я класс, я объявил контейнер, в котором будет находиться дерево.

final Composite container = new Composite(parent, SWT.NONE); 

Далее я звоню этот статический метод, который содержит фактического процесс сборки дерева

createTree(container); 

У меня есть какой-то другой код для кнопки и текстовой области для ввода данных пользователя, но не влияет на поведение программы или вызванное исключение.

Это статический метод createTree(container);

public void createTree(final Composite container){ 
    try{ 
     for(Object element : container.getChildren()){ 
      if(element instanceof Tree){ 
       ((Tree) element).dispose(); 
      } 
     }//here I am disposing of the previous tree and then I'm creating a new one to be drawn in the container when the layout() method will be called 

     final Tree variantTree = new Tree(container, SWT.CHECK | SWT.V_SCROLL | SWT.H_SCROLL); 
     variantTree.setBounds(10, 65, 400, 400); 

//here is where I am populating the tree with the data I have stored in the Tree Data Structure that I've mentioned 

     if(TestControl.getTree().getChildren().size() > 0){ 
      for(final Node variantElement : TestControl.getTree().getChildren()){ 
       final TreeItem variantTreeItem = new TreeItem(variantTree, 0); 
       variantTreeItem.setText(variantElement.getName()); 
       variantTreeItem.setChecked(variantElement.getState()); 

       for(Node suiteElement : variantElement.getChildren()){ 
        TreeItem suiteTreeItem = new TreeItem(variantTreeItem, 0); 
        suiteTreeItem.setText(suiteElement.getName()); 
        suiteTreeItem.setChecked(suiteElement.getState()); 

        for(Node testElement : suiteElement.getChildren()){ 
         TreeItem testTreeItem = new TreeItem(suiteTreeItem, 0); 
         testTreeItem.setText(testElement.getName()); 
         testTreeItem.setChecked(testElement.getState()); 
        } 
       } 
      } 
     } 
     //here is the actual problem, the exception's stack trace points to the line where my next comment is. this listener is used to bring a file dialog window where I can select a file and use it later on 

     variantTree.addListener(SWT.MouseDoubleClick, new Listener(){ 
      @Override 
      public void handleEvent(Event event) { 
       try{ 
        // TODO Auto-generated method stub 
        Point point = new Point(event.x, event.y); 
        if(!point.equals(null)){ 
         TreeItem item = variantTree.getItem(point); 
         for(Node element : TestControl.getTree().getChildren()){ 
          if(element.getName().equals(item.getText())){//here is the problem, why is it trying to tell me 

           FileDialog fileDialog = new FileDialog(container.getParent().getShell(), SWT.OPEN); 
           //filtering for extensions 
           //filtering for path 

           String path; 

           if((path = fileDialog.open()) != null){ 
            String fileName = fileDialog.getFileName(); 
            Node suiteNode = new Node(element); 
            suiteNode.setName(fileName); 
            TestControl.addChild(suiteNode); 


            createTree(container); 
//here I call the method in a recursive way. After I modified my Tree Data Structure with the data I got from the user, I want to redraw the tree in a real timed fashion 

           } 
          } 
         } 
        } 
       }catch(Exception exception){ 
        exception.printStackTrace(); 
        Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, exception.getLocalizedMessage(), exception); 
        ErrorDialog.openError(null, "Error", "Error occured!", status); 
       } 
      } 
     }); 

     variantTree.addListener(SWT.Selection, new Listener(){ 

      @Override 
      public void handleEvent(Event event) { 
       // TODO Auto-generated method stub 
       if(event.detail == SWT.CHECK){ 
        TreeItem item = (TreeItem) event.item; 

        for(Node element : TestControl.getTree().getChildren()){ 
         if(element.getName().equals(item.getText())){ 
          element.setState(item.getChecked()); 
         } 
        } 

        for(Node element : TestControl.getTree().getChildren()){ 
         for(Node nextElement : element.getChildren()){ 
          if(nextElement.getName().equals(item.getText())){//here the error doesnt show up, even though I am using the SWT Tree element as above 
           nextElement.setState(item.getChecked()); 
          } 
         } 
        } 

        for(Node element : TestControl.getTree().getChildren()){ 
         for(Node nextElement : element.getChildren()){ 
          for(Node lastElement : nextElement.getChildren()){ 
           if(lastElement.getName().equals(item.getText())){ 
            lastElement.setState(item.getChecked()); 
           } 
          } 
         } 
        } 
       } 
      } 
     }); 
    }catch(Exception exception){ 
     exception.printStackTrace(); 
     Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, exception.getLocalizedMessage(), exception); 
     ErrorDialog.openError(null, "Error", "Error occured!", status); 
    } 
} 

Я также читал, что может появиться эта ошибка, потому что, когда я звоню dispose, я должен избавиться от слушателей, а также. Нужно ли это быть источником исключения? Спасибо, и простите за часть кода обнимания.

ответ

1

Я предполагаю, что ошибка возникает, когда вы вызываете метод createTree после отображения FileDialog.

При вызове createTree вы в этом цикле:

for(Node element : TestControl.getTree().getChildren()){ 

так сразу после createTree вызова вы вернуться к началу цикла и запустить

if(element.getName().equals(item.getText())) 

но item здесь относится к TreeItem в Tree, который вы только что выбрали, поэтому он больше недействителен и вы получаете ошибку «виджета».

После того, как вы вызвали createTree, вы должны немедленно остановить цикл и не делать ничего другого на существующем дереве. break, чтобы остановить цикл будет достаточно здесь:

 createTree(container); 
     break; 

Примечание: Вы не должны распоряжаться Tree, просто удалив TreeItem с и добавление новых должно быть достаточно.

+0

Могу ли я избавиться от детей только дерева и сохранить одно и то же дерево? Хм, я попробую ваше решение, спасибо. – Justplayit94

+0

'Tree.removeAll' удаляет все существующие элементы дерева.Но вы все равно должны убедиться, что вы не ссылаетесь на удаленные предметы. –

+0

Это сработало, спасибо кучу. – Justplayit94