删除 JavaFX TreeItem 有时会更改 TreeTableView 选择
Removing a JavaFX TreeItem Sometimes Changes TreeTableView Selection
我有一个 JavaFX TreeTableView。在其根下,有一组 TreeItem(节点),每个节点可能有自己的子 TreeItem(子节点)。由于没有子节点的任何节点都没有可显示的信息,因此我想删除这些信息。但不知何故,简单的删除操作有时会改变选择。
package sample;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
TreeItem<String> rootNode = new TreeItem<String>("Root");
rootNode.setExpanded(true);
rootNode.getChildren().setAll(new TreeItem<>("Node 0"),
new TreeItem<>("Node 1"), new TreeItem<>("Node 2"),//);
new TreeItem<>("Node 3"), new TreeItem<>("Node 4"));
for (int i = 0; i < 2; i++) {
TreeItem<String> node = rootNode.getChildren().get(i);
node.setExpanded(true);
node.getChildren().setAll(new TreeItem<>("Sub Node " + i + "-0"),
new TreeItem<>("Sub Node " + i + "-1"),
new TreeItem<>("Sub Node " + i + "-2"));
}
TreeTableColumn<String, String> column = new TreeTableColumn<>("Nodes");
column.setCellValueFactory((TreeTableColumn.CellDataFeatures<String, String> p) -> {
return new ReadOnlyStringWrapper(p.getValue().getValue());
});
column.setPrefWidth(200);
TreeTableView<String> table = new TreeTableView<>(rootNode);
table.getColumns().add(column);
int selectIndex = 4;
int removeIndex = 3;
table.getSelectionModel().select(selectIndex);
System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex());
System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue());
table.getRoot().getChildren().remove(removeIndex);
System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex());
System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue());
primaryStage.setTitle("Tree Table View Selection");
primaryStage.setScene(new Scene(table, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
原样的代码产生以下输出:
Selected index = 4
Selected item = Sub Node 0-2
Selected index = 3
Selected item = Sub Node 0-1
但是,如果将(selectedIndex, removeIndex)改为(3,4),则输出变为:
Selected index = 3
Selected item = Sub Node 0-1
Selected index = 3
Selected item = Sub Node 0-1
所选索引没有变化。
事实上,在我有限的测试案例中,只要selectedIndex 小于或等于removeIndex,那么remove 动作就不会改变选择。否则它会更改选择。
为什么会这样?有办法解决这个问题吗?
这里发生的是你有一个选定的索引,而不是一个选定的项目,当你从树中删除节点时,选定的索引保持不变,但该索引处的项目现在不同了。
你的树是深度优先索引的,我认为,基于你打印出来的内容,所以将它作为项目映射的索引想象成一个数组,如下所示:["Root", "Node 0", "Sub Node 0-0", "Sub Node 0-1", "Sub Node 0-2", "Node 1", "Sub Node 1-1" ... "Sub Node 4-2"]
.
当您从这棵树中移除时,您也会从这个(可能是虚构的)数组中移除。你删除了一些东西,所有索引大于它的东西都会向下移动一个位置。
为了处理这个问题,您需要简单地检查以在删除项目后正确更新 selectIndex,以便匹配其新索引。您可以执行以下操作:
if(selectIndex > removeIndex)
selectIndex--;
这似乎是 java 中的错误。我向 bugs.java.com 报告了它,它现在被列为 JDK-8193442,目前还没有修复。
解决方法是在移除 TreeItem 之前保存 selectedItem,并在移除之后调用 select。不过,需要注意 selectedItemProperty 上的任何更改侦听器。
我有一个 JavaFX TreeTableView。在其根下,有一组 TreeItem(节点),每个节点可能有自己的子 TreeItem(子节点)。由于没有子节点的任何节点都没有可显示的信息,因此我想删除这些信息。但不知何故,简单的删除操作有时会改变选择。
package sample;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
TreeItem<String> rootNode = new TreeItem<String>("Root");
rootNode.setExpanded(true);
rootNode.getChildren().setAll(new TreeItem<>("Node 0"),
new TreeItem<>("Node 1"), new TreeItem<>("Node 2"),//);
new TreeItem<>("Node 3"), new TreeItem<>("Node 4"));
for (int i = 0; i < 2; i++) {
TreeItem<String> node = rootNode.getChildren().get(i);
node.setExpanded(true);
node.getChildren().setAll(new TreeItem<>("Sub Node " + i + "-0"),
new TreeItem<>("Sub Node " + i + "-1"),
new TreeItem<>("Sub Node " + i + "-2"));
}
TreeTableColumn<String, String> column = new TreeTableColumn<>("Nodes");
column.setCellValueFactory((TreeTableColumn.CellDataFeatures<String, String> p) -> {
return new ReadOnlyStringWrapper(p.getValue().getValue());
});
column.setPrefWidth(200);
TreeTableView<String> table = new TreeTableView<>(rootNode);
table.getColumns().add(column);
int selectIndex = 4;
int removeIndex = 3;
table.getSelectionModel().select(selectIndex);
System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex());
System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue());
table.getRoot().getChildren().remove(removeIndex);
System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex());
System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue());
primaryStage.setTitle("Tree Table View Selection");
primaryStage.setScene(new Scene(table, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
原样的代码产生以下输出:
Selected index = 4
Selected item = Sub Node 0-2
Selected index = 3
Selected item = Sub Node 0-1
但是,如果将(selectedIndex, removeIndex)改为(3,4),则输出变为:
Selected index = 3
Selected item = Sub Node 0-1
Selected index = 3
Selected item = Sub Node 0-1
所选索引没有变化。
事实上,在我有限的测试案例中,只要selectedIndex 小于或等于removeIndex,那么remove 动作就不会改变选择。否则它会更改选择。
为什么会这样?有办法解决这个问题吗?
这里发生的是你有一个选定的索引,而不是一个选定的项目,当你从树中删除节点时,选定的索引保持不变,但该索引处的项目现在不同了。
你的树是深度优先索引的,我认为,基于你打印出来的内容,所以将它作为项目映射的索引想象成一个数组,如下所示:["Root", "Node 0", "Sub Node 0-0", "Sub Node 0-1", "Sub Node 0-2", "Node 1", "Sub Node 1-1" ... "Sub Node 4-2"]
.
当您从这棵树中移除时,您也会从这个(可能是虚构的)数组中移除。你删除了一些东西,所有索引大于它的东西都会向下移动一个位置。
为了处理这个问题,您需要简单地检查以在删除项目后正确更新 selectIndex,以便匹配其新索引。您可以执行以下操作:
if(selectIndex > removeIndex)
selectIndex--;
这似乎是 java 中的错误。我向 bugs.java.com 报告了它,它现在被列为 JDK-8193442,目前还没有修复。
解决方法是在移除 TreeItem 之前保存 selectedItem,并在移除之后调用 select。不过,需要注意 selectedItemProperty 上的任何更改侦听器。