I am writing a program in Codenameone that will pull an array of products from a url and display them in a list. I want to reload the page every time I press a button, so I code in a method called reload that should delete everything in the form and then replace it all with the newly pulled list.
public void reload(Form list){
list.removeAll();
list.repaint();
list.add(lpanelf);
pull();
for(int i=0; i<(products.size());i++){
System.out.println(products.get(i));
}
for(int i = 0; i<(products.size()/2);i++){
list.add(createWidget(products.get(i*2),products.get(i*2+1),i));
}
list.addComponent(lpanelb);
}
And createWidget is:
public SwipeableContainer createWidget(String product, String amount,int i) {
MultiButton button = new MultiButton(product);
Button buttonb = new Button("DELETE");
deleteb.add(button);
slide.add(buttonb);
button.setLayout(new GridLayout(1,2));
button.add(amount);
return new SwipeableContainer(slide.get(i),deleteb.get(i));
}
After the first time it reloads, it throws:
java.lang.IllegalArgumentException: Component is already contained in Container: Container[x=0 y=0 width=1125 height=165 name=null, layout = BorderLayout, scrollableX = false, scrollableY = false, components = [Button]].
I think the problem is that removeAll isn't actually removing all the swipable containers and so it won't let me create new ones in their place but I am not too sure. Any help would be greatly appreciated.
removeAll()
doesn't recurse. That would be expensive and often redundant since the GC usually removes the entire tree.
Typically these problems are pretty simple to workaround though. There are two approaches:
Stop caching the component and re-create it every time you reload. This will mean it's never "already in" something
Before adding the problematic component just do: problematicComponent.remove()
. This will remove it from its parent (or do nothing if it has no parent)
In your case it seems like you're doing this:
return new SwipeableContainer(slide.get(i),deleteb.get(i));
After doing stuff linke this:
slide.add(buttonb);
So you added buttonb
to slide
. That means that buttonb.getParent() == slide
. Then you create a new SwipableContainer
and try to add into it a component that's already in it.
I'm guessing here since you didn't say which specific line threw the exception but on that line you will find the problematic component.
Also this line is problematic: button.add(amount);
You're relying on the fact that MultiButton
inherits from Container
but that's fragile behavior. You should use one of the set text line methods.