JavaFX从TableView删除

时间:2018-09-21 19:01:21

标签: java javafx tableview

我正在使用JavaFX应用,并且正在将TableView用作GUI的一部分,如下所示:

$ sed -E 's/(rc\([0-9]+)(\s+?)([a-zA-Z0-9]+?\))/\1-\3/g' x.log
rc(200-OK) rc(403-Unauthorized) rc()
$ 

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

public TableView<Meal> meals;

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

研究了一段时间之后,我偶然发现了一段解决问题的代码。这是具有有效代码的方法:

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

    mealsSelected.forEach(allMeals::remove);
}

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

谢谢。

1 个答案:

答案 0 :(得分:1)

TableView的选择模型必须遵守ObservableList属性中的items,才能正确反映表的状态。换句话说,如果从items中删除了元素,则还必须从选择模型的选定项中删除它。

这导致您在迭代selectedMeals列表以从meals列表中删除包含的元素的同时间接修改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)); 来简化代码。

config.xml