[英]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.