如何在Codenameone上删除表单中的所有组件?

How to delete all components in a form on Codenameone?

我正在用 Codenameone 编写一个程序,它将从 url 中提取一系列产品并将它们显示在列表中。我想在每次按下按钮时重新加载页面,所以我编写了一个名为 reload 的方法,该方法应删除表单中的所有内容,然后将其全部替换为新拉出的列表。

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);

}

而 createWidget 是:

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));

}

第一次重新加载后,抛出:

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

我认为问题是 removeAll 实际上并没有删除所有可滑动的容器,所以它不会让我在它们的位置创建新的容器,但我不太确定。任何帮助将不胜感激。

removeAll() 不递归。由于 GC 通常会删除整棵树,因此这样做会很昂贵并且通常是多余的。

通常这些问题很容易解决。有两种方法:

  • 停止缓存组件并在每次重新加载时重新创建它。这将意味着它永远不会“已经在”某物中

  • 在添加有问题的组件之前,只需执行:problematicComponent.remove()。这会将它从其父项中删除(或者如果它没有父项则什么都不做)

在你的情况下,你似乎是这样做的:

return new SwipeableContainer(slide.get(i),deleteb.get(i));

完成链接后:

slide.add(buttonb);

因此您将 buttonb 添加到 slide。这意味着 buttonb.getParent() == slide。然后你创建一个新的 SwipableContainer 并尝试向其中添加一个已经存在的组件。

我猜是因为你没有说明是哪一行引发了异常,但在那一行你会发现有问题的组件。

这一行也有问题:button.add(amount);

您依赖于 MultiButton 继承自 Container 这一事实,但这是脆弱的行为。您应该使用其中一种设置文本行的方法。