繁体   English   中英

从 TableView 中删除 JavaFX

[英]JavaFX deleting from TableView

我正在开发 JavaFX 应用程序,并使用 TableView 作为 GUI 的一部分,如下所示:

public TableView<Meal> meals;

并为其分配了一个按钮,该按钮应该删除选定的元素。 为此,我使用了一个不断给我 NoSuchElementException 的函数

public void deleteMealButtonClicked()
{
    ObservableList<Meal> mealsSelected = meals.getSelectionModel().getSelectedItems();
    ObservableList<Meal> allMeals = meals.getItems();

    mealsSelected.forEach(allMeals::remove);
}

我通过调试发现问题出在方法的最后一行。

研究了半天,偶然发现一段代码解决了这个问题。 这是具有有效代码的方法:

public void deleteMealButtonClicked()
{
    ObservableList<Meal> mealsSelected = meals.getSelectionModel().getSelectedItems();
    ObservableList<Meal> allMeals = meals.getItems();

    if (mealsSelected != null) {
        ArrayList<Meal> rows = new ArrayList<>(mealsSelected);
        rows.forEach(row -> meals.getItems().remove(row));
    }
}

我的问题是,为什么第二种方法有效而不是第一种方法? 除了将所选行添加到第二种方法的 ArrayList 之外,它们从根本上不是一回事吗?

先感谢您。

TableView的选择模型必须观察items属性中的ObservableList才能正确反映表格的状态。 换句话说,如果一个元素从items删除,它也必须从选择模型的选定项目中删除。

这导致您在迭代它以从meals列表中删除包含的元素时间接修改selectedMeals列表。 在很多java.util集合中,迭代器是快速失败的,这将导致ConcurrentModificationException 我猜选择模型不是快速失败的,因此您只会看到不确定的行为(以NullPointerException的形式)。

第二个选项有效,因为您首先制作selectedMeals的副本,然后迭代该副本。

您在评论中要求不创建副本的方法; 不幸的是,我想不出一个。 但是,您可以使用removeAll稍微简化您的代码。

ObservableList<Meal> selected = ...;

// List.copyOf is a Java 10 method (and doesn't accept null elements)
table.getItems().removeAll(List.copyOf(selected));

// Pre Java 10 you can use toArray since ObservableList overloads removeAll
// with a version that takes a varargs parameter
table.getItems().removeAll(selected.toArray(new Meal[0]));

// or use the copy constructor of many collection classes
table.getItems().removeAll(new ArrayList<>(selected));

// In Java 11, toArray can be replaced with
table.getItems().removeAll(selected.toArray(Meal[]::new));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM