如何在 JavaFX 的 TreeTableView 中可视化无限数量的数据行?
How to visualize UNLIMITED number of rows of data in TreeTableView in JavaFX?
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);
}
}
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);
}
}