Ответ 1
Вы правы, событие должно содержать два отдельных "удаления" изменений. Начиная с версии 1.8.0_74 модель выбора TreeTableView кажется безнадежно разбитой. Это даже не согласуется с моделью выбора TreeView, которая также является винтовой (но тем более). Существует так много режимов сбоев, существующих ошибок и ошибок регрессии, которые трудно определить, знает ли Oracle о проблеме. Я предлагаю подать еще один баг. Ниже код обеспечивает достойную песочницу для воспроизведения с функцией.
public class Test extends Application {
public void start(Stage pStage) {
pStage.setTitle("Test");
final TabPane tabPane = new TabPane();
tabPane.getTabs().addAll(
Stream.of(true, false).map(
pIsTreeTable -> {
final Tab result = new Tab(pIsTreeTable ? "TreeTableView" : "TreeView");
// create tree model
final TreeItem<String> root = new TreeItem<>("Root Node");
root.setExpanded(true);
final Collection<TreeItem<String>> children = IntStream.rangeClosed(
1, 5
).mapToObj(pIdx -> new TreeItem<>("Child Node " + pIdx)).collect(
Collectors.toList()
);
// create TreeView or TreeTableView
final Control tree;
final MultipleSelectionModel<TreeItem<String>> selectionModel;
if (pIsTreeTable) {
final TreeTableView<String> treeTableView = new TreeTableView<>(
root
);
final TreeTableColumn<String,String> column = new TreeTableColumn<>(
"Column"
);
column.setCellValueFactory(
pTreeItem -> new ReadOnlyStringWrapper(
pTreeItem.getValue().getValue()
)
);
treeTableView.getColumns().add(column);
tree = treeTableView;
selectionModel = treeTableView.getSelectionModel();
} else {
final TreeView<String> treeView = new TreeView<>(root);
tree = treeView;
selectionModel = treeView.getSelectionModel();
}
selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
// add buttons
final ToggleButton childrenBtn = new ToggleButton("Children");
childrenBtn.selectedProperty().addListener(
(pObservable, pOldVal, pNewVal) -> {
if (pNewVal) {
root.getChildren().addAll(children);
} else {
root.getChildren().clear();
}
}
);
childrenBtn.setSelected(true);
final ToggleButton showRootBtn = new ToggleButton("Show Root");
showRootBtn.setSelected(true);
(
pIsTreeTable ?
((TreeTableView<?>) tree).showRootProperty() :
((TreeView<?>) tree).showRootProperty()
).bind(showRootBtn.selectedProperty());
// 'getSelectedItems()' tab
final Tab selectedItemsTab = new Tab("getSelectedItems()");
final TextArea selectedItemsTextArea = new TextArea();
selectionModel.getSelectedItems().addListener(
(ListChangeListener<TreeItem<String>>) pChange -> {
while (pChange.next()) {
if (pChange.getRemovedSize() > 0) {
selectedItemsTextArea.appendText(
"Removed " + pChange.getRemoved() + '\n'
);
}
if (pChange.getAddedSize() > 0) {
selectedItemsTextArea.appendText(
"Added " + pChange.getAddedSubList() + '\n'
);
}
}
selectedItemsTextArea.appendText(
"Selection: " + pChange.getList() + "\n\n"
);
}
);
selectedItemsTab.setContent(selectedItemsTextArea);
// 'getSelectedItem()' tab
final Tab selectedItemTab = new Tab("getSelectedItem()");
final TextArea selectedItemTextArea = new TextArea();
selectionModel.selectedItemProperty().addListener(
(pObservable, pOldVal, pNewVal) -> {
selectedItemTextArea.appendText("Selected " + pNewVal + '\n');
}
);
selectedItemTab.setContent(selectedItemTextArea);
// display selection data in text area
final TabPane selectionTabPane = new TabPane();
selectionTabPane.getTabs().addAll(selectedItemsTab, selectedItemTab);
final SplitPane splitPane = new SplitPane(
tree, new HBox(showRootBtn, childrenBtn), selectionTabPane
);
splitPane.setOrientation(Orientation.VERTICAL);
result.setContent(splitPane);
return result;
}
).collect(Collectors.toList())
);
pStage.setScene(new Scene(tabPane, 300, 450));
pStage.show();
}
public static void main(String[] pArgs) {launch(pArgs);}
}
Связанные (?) вопросы:
- Нажмите кнопку "Ctrl"
- Выберите "Ребенок Node 2"
- Выберите "Ребенок Node 3"
- Выберите "Ребенок Node 1"
Событие ListChangeListener.Change означает, что выбрано "Child Node 2".
- Выберите "Root Node"
- Отмените выбор кнопки "Показать корень"
"Ребенок Node 1" выбран, но событие выбора не передается.
- Выберите "Ребенок Node 2"
- Отмените выбор кнопки "Дети".
'selection' содержит нуль.
- Выберите "Ребенок Node 1"
- Свернуть "Root Node"
Событие ListChangeListener.Change не включает удаление.
- Отмените выбор кнопки "Дети".
- Выберите "Root Node"
- Отмените выбор кнопки "Показать корень"
Событие транслируется ни для TreeView, ни для TreeTableView. Оттуда, если нажата кнопка "Показать корень" , TreeView передает событие, но TreeTableView этого не делает.