如何在 JavaFX 的 TreeTableView 中可视化无限数量的数据行?

How to visualize UNLIMITED number of rows of data in TreeTableView in JavaFX?

said in documentation,那

TreeTableView control is designed to visualize an unlimited number of rows of data

不幸的是,我在文档中看不到任何方法。

所有元素都存储在TreeItem<>类中,存储在内存中。虽然,可以用 ObservableList<> 实现 "unlimitness",但我认为没有办法在嵌套的可观察列表上实现它。

"Unlimitness"需要按需加载数据,而不是存储在内存中。

那么TreeTableView终于可以按需显示数据了吗?

正如评论中指出的那样,documentation for TreeItem 有一个延迟填充树项的子节点的示例。

这是一个非常简单的无限树完整示例 table。在此示例中,折叠树项时会删除子节点,从而可以对它们进行垃圾回收。

import java.math.BigInteger;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
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 UnlimitedTreeTableView extends Application {


    @Override
    public void start(Stage primaryStage) {
        TreeTableView<Item> treeTable = new TreeTableView<>();
        treeTable.setRoot(createTreeItem(BigInteger.ZERO));

        treeTable.getColumns().add(column("Item", Item::getName));
        treeTable.getColumns().add(column("Value", Item::getValue));

        primaryStage.setScene(new Scene(treeTable));
        primaryStage.show();
    }

    private TreeItem<Item> createTreeItem(BigInteger value) {
        TreeItem<Item> item = new TreeItem<Item>(new Item(String.format("Item %,d", value), value)) {

            private boolean childrenComputed = false ;

            {
                expandedProperty().addListener((obs, wasExpanded, isNowExpanded) -> {
                    if (! isNowExpanded) { // remove child nodes...
                        super.getChildren().clear();
                        childrenComputed = false ;
                    }
                });
            }

            @Override
            public ObservableList<TreeItem<Item>> getChildren() {
                if (! childrenComputed) {
                    Item item = getValue();
                    BigInteger value = item.getValue() ;
                    BigInteger valueTimes10 = value.multiply(BigInteger.TEN);
                    for (int i = 0 ; i < 10 ; i++) {
                        BigInteger v = BigInteger.valueOf(i);
                        super.getChildren().add(createTreeItem(valueTimes10.add(v)));
                    }
                    childrenComputed = true ;
                }
                return super.getChildren();
            }

            @Override
            public boolean isLeaf() {
                return false ;
            }
        };

        return item ;
    }

    private static <S,T> TreeTableColumn<S,T> column(String title, Function<S,T> property) {
        TreeTableColumn<S,T> column = new TreeTableColumn<>(title);
        column.setCellValueFactory(cellData -> 
            new SimpleObjectProperty<T>(property.apply(cellData.getValue().getValue())));
        column.setPrefWidth(200);
        return column ;
    }

    public static class Item {
        private final BigInteger value ;
        private final String name ;

        public Item(String name, BigInteger value) {
            this.name = name ;
            this.value = value ;
        }

        public BigInteger getValue() {
            return value;
        }

        public String getName() {
            return name;
        }


    }

    public static void main(String[] args) {
        launch(args);
    }
}