简体   繁体   English

Java SWT Tree TreeItem侦听器返回窗口小部件处置异常错误

[英]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. 我编写了一个程序,该程序通过文本框,按钮和文件对话框从用户处获取多个输入,并将其格式化为SWT树,用户可以在其中通过复选框选择元素。

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. 我面临的问题是我希望它为用户实时更新,并且我在这个论坛中找到了一个有关使用容器的layout()方法的解决方案,它可以与我的树一起使用,但前提是在这棵树上调用dispose() ,然后重建它/之后重新绘制它。

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. 另外,我正在使用的类实现了SWT的Dialog接口,因此当我按下按钮时,将显示一个带有树和文本输入区域的窗口。

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); 这是静态方法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. 我还读到可能会出现此错误,因为当我调用dispose ,我也应该摆脱监听器。 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 . 我假设在显示FileDialog之后调用createTree方法时发生错误。

When you call the createTree you are in this loop: 当您调用createTree您将处于以下循环中:

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

so immediately after the createTree call you go back to the start of the loop and run 因此,在createTree调用之后,您立即返回到循环的起点并运行

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. 但此处的item是指您刚刚处置的Tree中的TreeItem ,因此它不再有效,并且会收到“处置的部件”错误。

After calling createTree you must stop your loop immediately and not do anything else on the existing tree. 调用createTree ,必须立即停止循环,并且不要对现有树进行任何其他操作。 A break to stop the loop would be enough here: break循环就足够了:

       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. 注意:您不必丢弃Tree ,只需删除TreeItem并添加新的就足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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