JavaFX:TreeView selectedItems 的 bindContent
JavaFX: bindContent of TreeView selectedItems
我想绑定 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
个项目。 Select 在树中查看从 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
-------------------
您可以看到 "removed at 6" 然后是 "removed at 7",但是基础列表的大小也发生了变化,因此不应在此处增加索引,即所有 "removed at" 都应为 6。并且由于这个 Bindings.bindContent 失败了。
这是一个错误 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()));
}
});
我想绑定 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
个项目。 Select 在树中查看从 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
-------------------
您可以看到 "removed at 6" 然后是 "removed at 7",但是基础列表的大小也发生了变化,因此不应在此处增加索引,即所有 "removed at" 都应为 6。并且由于这个 Bindings.bindContent 失败了。
这是一个错误 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()));
}
});