1

我有一个 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 操作不会改变选择。否则它会改变选择。

为什么会这样?有没有办法解决这个问题?

4

2 回答 2

1

看来这是java中的一个错误。我向 bugs.java.com 报告了它,现在它被列为JDK-8193442,目前还没有修复。

一种解决方法是在删除 TreeItem 之前保存 selectedItem,并在删除后调用 select。不过,需要注意 selectedItemProperty 上的任何更改侦听器。

于 2017-12-13T14:55:01.320 回答
0

这里发生的情况是您有一个选定的索引,而不是选定的项目,当您从树中删除节点时,选定的索引保持不变,但该索引处的项目现在不同了。

我认为,根据您打印的内容,您的树是深度优先索引的,因此将其对项目映射的索引想象为一个如下所示的数组["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--;
于 2017-12-12T21:07:52.047 回答