我想绑定TreeView所选项目列表的内容,并在删除元素时碰到所选项目更改值的奇怪行为。我写了一些测试应用程序:
public class TreeViewSelectedItemsBindingTest extends Application {
public class Item extends TreeItem<Integer> {
public Item(Integer... value) {
Arrays.stream(value).forEach(v -> getChildren().add(new TreeItem<Integer>(v)));
}
}
@Override
public void start(Stage primaryStage) throws Exception {
TreeView<Integer> treeView = new TreeView<>();
treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
treeView.setRoot(new Item(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
treeView.getRoot().setExpanded(true);
treeView.setShowRoot(false);
ListView<TreeItem<Integer>> listView = new ListView<>();
Bindings.bindContent(listView.getItems(), treeView.getSelectionModel().getSelectedItems());
treeView.getSelectionModel().getSelectedItems()
.addListener((ListChangeListener<? super TreeItem<Integer>>) change -> {
System.out.println("Change: " + change);
System.out.println("TreeView size: " + treeView.getSelectionModel().getSelectedItems().size());
System.out.println("ListView size: " + listView.getItems().size());
System.out.println("-------------------");
});
HBox box = new HBox();
box.getChildren().addAll(treeView, listView);
primaryStage.setScene(new Scene(box));
primaryStage.show();
}
static public void main(String[] args) {
launch(args);
}
}
此应用程序将TreeView
个选定项目绑定到ListView
个项目。在树视图中选择从0到9的所有元素,然后按SHIFT
+元素5,例如,将选择从0更改为5个元素。你会得到一个例外:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: toIndex = 9
这是因为ListChangeListener.Change从索引相对于初始未修改列表报告,而不是相对于先前更改的列表:
-------------------
Change: { [TreeItem [ value: 6 ]] removed at 6, }
TreeView size: 9
ListView size: 9
-------------------
Change: { [TreeItem [ value: 7 ]] removed at 7, }
TreeView size: 8
ListView size: 8
-------------------
你可以看到&#34;在6&#34;然后&#34;在7&#34;删除,但基础列表的大小也发生了变化,所以索引不应该在这里增加,即所有&#34;删除&#34;应该是6.因此,Bindings.bindContent失败。
答案 0 :(得分:0)
这是一个错误JDK-8180359。作为一种解决方法,绑定列表应该整体更新:
treeView.getSelectionModel().getSelectedItems().addListener(
(ListChangeListener<? super TreeItem<Model>>) change -> {
while (change.next()) {
listView.setAll(change.getList().stream()
.filter(Objects::nonNull)
.map(i -> i.getValue())
.collect(toList()));
}
});