简体   繁体   中英

Java SWT Tree TreeItem Listener return a Widget Disposed Exception Error

I have made a program that takes several inputs from user via a text box and a button and a file dialog, and the formats them into a SWT tree, in which the user can select via checkboxes it's elements.

The problem I'm facing is that I want it to update in real time for the user, and I've found a solution in this forum about using the container's layout() method, and it works with my tree, but only if I call the dispose() on this tree, and then rebuilding it/ redrawing it afterwards.

Behind this tree I have a Tree Data Structure that I use to manage all the data. Also, the class I'm using implements SWT's Dialog interface, so that when I press a button, a window with the tree and text input area will show up.

I the class I've declared the container in which the tree will reside.

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

Next I'm calling this static method that contains the actual build process of the tree

createTree(container);

I have some other code for a the button and text area for the user input, but that doesn't impact the behavior of the program or the thrown exception.

This is the static method 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);
    }
}

I've also read that this error might appear because when I am calling dispose , I should get rid of the listeners as well. Is it necessary, this might be the source for the exception? Thanks, and sorry for the hug code part.

I assume the error occurs when you call the createTree method after displaying the FileDialog .

When you call the createTree you are in this loop:

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

so immediately after the createTree call you go back to the start of the loop and run

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

but the item here refers to a TreeItem in the Tree that you have just disposed so it is no longer valid and you get the 'widget disposed' error.

After calling createTree you must stop your loop immediately and not do anything else on the existing tree. A break to stop the loop would be enough here:

       createTree(container);
       break;

Note: You shouldn't have to dispose of the Tree , just removing the TreeItem s and adding new ones should be enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM