Проблема
Когда элементы удаляются из ObservableList
, событие изменения запускается там, где getFrom()
указывает местоположение удаления и getRemoved()
предоставляет список элементов, которые были удалены. В документации говорится:
Метод
getRemoved()
возвращает список элементов, которые были заменены или удалены из списка.
Он не указывается как таковой, но я полагал, что это означает, что список элементов является смежным суб-списком из исходного списка. Я написал много кода с этим допущением, но теперь я сталкиваюсь с трудностями с TreeTableView
моделью выбора, которая не ведет себя таким образом.
Пример
Возьмем, к примеру, простую таблицу деревьев с тремя строками "Node". Если я выберу эти три строки...
... и затем щелкните и выберите только среднюю строку...
... событие изменения, запущенное на treeTableView.getSelectionModel().getSelectedItems()
, выглядит следующим образом:
{ [TreeItem [ value: Node 1 ], TreeItem [ value: Node 3 ]] removed at 0, }
В одном событии изменения сообщается, что "Node 1" и "Node 3" были удалены из индекса 0 списка selectedItems
.
Я бы ожидал, что объект Change
будет иметь два отдельных события удаления, разделенных вызовами next()
. Первый вызов next()
сказал бы мне, что "Node 1" был удален с индексом 0, а второй вызов next()
сказал бы мне, что "Node 3" был удален с индексом 1. Но нет, Я получаю одно событие с двумя строками, перечисленными сразу.
Вопрос
Может ли getRemoved()
действительно возвращать несмежные элементы? Является ли это недоразумением в моей части того, как работают события изменения списка, или это ошибка в TreeTableView
?
Обычно я не решаюсь обвинять стандартные библиотеки, но это не будет первой ошибкой, которую я нашел в JavaFX, поэтому это немыслимо.
Update
Если я добавлю вызов setShowRoot(false)
, поведение изменится. Я получаю то, что ожидаю, удаление разбивается на две части:
{ [TreeItem [ value: Node 1 ]] removed at 0, [TreeItem [ value: Node 3 ]] removed at 1, }
Кроме того, вот мой MCVE:
import java.util.*;
import javafx.application.*;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.stage.*;
public class TreeTableSelectionEvents extends Application {
public void start(Stage stage) {
// Root node.
TreeItem<String> root = new TreeItem<>("Root");
root.setExpanded(true);
root.getChildren().setAll(Arrays.asList(
new TreeItem<>("Node 1"),
new TreeItem<>("Node 2"),
new TreeItem<>("Node 3")
));
// Single column.
TreeTableColumn<String, String> column = new TreeTableColumn<>("Column");
column.setPrefWidth(150);
column.setCellValueFactory((TreeTableColumn.CellDataFeatures<String, String> p) -> {
return new ReadOnlyStringWrapper(p.getValue().getValue());
});
// Tree table.
TreeTableView<String> table = new TreeTableView<>(root);
table.getColumns().add(column);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// table.setShowRoot(false);
table.getSelectionModel().getSelectedItems().addListener(
(ListChangeListener.Change<? extends TreeItem<String>> change) -> {
System.out.printf("item change = %s, list is now %s%n", change, change.getList());
}
);
table.getSelectionModel().getSelectedIndices().addListener(
(ListChangeListener.Change<? extends Integer> change) -> {
System.out.printf("index change = %s, list is now %s%n", change, change.getList());
}
);
// Stage.
stage.setScene(new Scene(table));
stage.show();
}
}