Reputation: 423
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.
Upvotes: 0
Views: 448
Reputation: 111142
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.
Upvotes: 1