簡體   English   中英

Java SWT Tree TreeItem偵聽器返回窗口小部件處置異常錯誤

[英]Java SWT Tree TreeItem Listener return a Widget Disposed Exception Error

我編寫了一個程序,該程序通過文本框,按鈕和文件對話框從用戶處獲取多個輸入,並將其格式化為SWT樹,用戶可以在其中通過復選框選擇元素。

我面臨的問題是我希望它為用戶實時更新,並且我在這個論壇中找到了一個有關使用容器的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 ,我也應該擺脫監聽器。 是否有必要,這可能是異常的來源? 謝謝,對不起,擁抱代碼部分。

我假設在顯示FileDialog之后調用createTree方法時發生錯誤。

當您調用createTree您將處於以下循環中:

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

因此,在createTree調用之后,您立即返回到循環的起點並運行

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

但此處的item是指您剛剛處置的Tree中的TreeItem ,因此它不再有效,並且會收到“處置的部件”錯誤。

調用createTree ,必須立即停止循環,並且不要對現有樹進行任何其他操作。 break循環就足夠了:

       createTree(container);
       break;

注意:您不必丟棄Tree ,只需刪除TreeItem並添加新的就足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM