JavaFX 无法从 ArrayList 中删除项目

JavaFX troubles with removing items from ArrayList

我有 2 个 TableViewtableProducttableProduct2)。第一个由数据库填充,第二个由用户从第一个中选择的项目填充(addMeal 方法,它也将这些转换为简单的 ArrayList)。在 adding/deleting 个对象之后,用户可以将当前数据从第二个 Table 保存到 txt 文件。一开始似乎工作得很好。但是问题开始有点随机出现......我添加了一些项目,保存,删除了一些项目,保存,一切都很好。然后在这样的几次操作之后,最后一个对象保留在 txt 文件中,即使 TableView 是空的。我无法做任何事情来删除它,而且我没有收到任何错误...

有什么想法吗?

 public void addMeal() {
    productData selection = tableProduct.getSelectionModel().getSelectedItem();
    if (selection != null) {
        tableProduct2.getItems().add(new productData(selection.getName() + "(" + Float.parseFloat(weightField.getText()) + "g)", String.valueOf(Float.parseFloat(selection.getKcal())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getProtein())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getCarb())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getFat())*(Float.parseFloat(weightField.getText())/100))));
        productlist.add(new productSimpleData(selection.getName() + "(" + Float.parseFloat(weightField.getText()) + "g)", String.valueOf(Float.parseFloat(selection.getKcal())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getProtein())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getCarb())*(Float.parseFloat(weightField.getText())/100)), String.valueOf(Float.parseFloat(selection.getFat())*(Float.parseFloat(weightField.getText())/100))));
    }
    updateSummary();
    }


public void deleteMeal() {
    productData selection = tableProduct2.getSelectionModel().getSelectedItem();

    if(selection != null){
        tableProduct2.getItems().remove(selection);
        Iterator<productSimpleData> iterator = productlist.iterator();

                    productSimpleData psd = iterator.next();
                    if(psd.getName().equals(String.valueOf(selection.getName()))) {
                        iterator.remove();
                }

    }
    updateSummary();
}

public void save() throws IOException {

    File file = new File("C:\Users\Maciek\Desktop\test1.txt");
    if(file.exists()){
        file.delete();
    }
    FileWriter fw = null;
    BufferedWriter bw = null;

    try {
        fw = new FileWriter(file);
        bw = new BufferedWriter(fw);
        Iterator iterator;
        iterator = productlist.iterator();
        while (iterator.hasNext()) {
            productSimpleData pd;
            pd = (productSimpleData) iterator.next();
            bw.write(pd.toString());
            bw.newLine();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        bw.flush();
        bw.close();
    }
}

是的,我意识到 addMethod 里面的 if 语句看起来很可怕,但不要介意,毕竟那部分没问题...

您只需检查 productlist 列表中的第一项以确定是否应删除该项。由于在不对 tableProduct2items 进行类似修改的情况下,您似乎不会在任何地方写入 List,因此在这种情况下您也可以这样做。

public void deleteMeal() {
    int selectedIndex = tableProduct2.getSelectionModel().getSelectedIndex();

    if(selectedIndex >= 0) {
        tableProduct2.getItems().remove(selectedIndex);
        productlist.remove(selectedIndex);
    }
    updateSummary();
}

如果列表中有 2 个相同的项目,这可能会导致在选择第二个项目时删除第一个项目,这样您还可以防止出现问题...


and yeah, I realize addMethod [...] looks scary

是的,是的,所以是时候重写这个了:

productDataproductSimpleData 中的属性更改为 float,并且在需要 String 之前不要将数据转换为 String

if (selection != null) {
    float weight = Float.parseFloat(weightField.getText());
    float weight100 = weight / 100;

    float calories = Float.parseFloat(selection.getKcal())*weight100;
    float protein = Float.parseFloat(selection.getProtein())*weight100;
    float carb = Float.parseFloat(selection.getCarb())*weight100;
    float fat = Float.parseFloat(selection.getFat())*weight100;

    ProductData product = new productData(
                               selection.getName() + "(" + weight + "g)",
                               calories,
                               protein,
                               carb,
                               fat);
    productlist.add(new productSimpleData(product.getName(), calories, protein, carb, fat));
    tableProduct2.getItems().add(product);
}

另外这种循环可以重写为增强的for循环:

Iterator iterator;
iterator = productlist.iterator();
while (iterator.hasNext()) {
    productSimpleData pd;
    pd = (productSimpleData) iterator.next();
    bw.write(pd.toString());
    bw.newLine();
}

假设您已将 productlist 声明为 List<productSimpleData> 或子类型,您可以只做

for (productSimpleData pd : productlist) {
    bw.write(pd.toString());
    bw.newLine();
}

此外,您可以依靠 try-with-resources 为您关闭编写器:

try (FileWriter fw = new FileWriter(file);
     BufferedWriter bw = new BufferedWriter(fw)){
    ...
} catch (IOException e) {
    e.printStackTrace();
}

也不需要删除该文件,因为 java 默认情况下会覆盖该文件,并且仅当您在 FileWriter.

的附加构造函数参数中指定时才附加数据