具有作为对象字段的子节点的对象的 TreeView

Kev*_*ong 0 java data-binding model-view-controller treeview javafx

我有一个包含不同数据类型字段的对象:

public class MyObject{
     private String field1;
     private CustomObject field2;
     private int field3;
     ...
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个MyObject具有多个MyObject节点的树视图,每个节点都有字段(field1field2field3..etc )作为子节点。

我知道我可以制作一个字符串的 TreeView 并使用 addNode(MyObject obj) 方法自行填充它,在该方法中我将添加我需要的各个 TreeItems。但是,我使用 TableView 执行此操作,其中我能够将列与字段属性绑定。例如:

TableView<MyObject> table;
TableColumn<MyObject, String> myColumn;
myColumn.setCellValueFactory(new PropertyValueFactory<>("field1"));
Run Code Online (Sandbox Code Playgroud)

有什么办法可以为 a 做类似的事情吗TreeView<MyObject>?我不反对创建一个扩展的子类TreeItem<?>

我正在寻找的最终结果将是这样的:

--> First My Object
    ->field1: "Value at Field 1"
    ->field2: "Value at Field 2"
    ->field3: 3
--> Second My Object
    ->field1: "Value at Field 1"
    ->field2: "Value at Field 2"
    ->field3: 3
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 5

几乎任何时候你TreeView在树的不同节点中使用不同类型的 a 时,你都需要在某处进行一些转换和/或类型检查。

这里一种可能的方法是子类化,TreeItem为要显示的属性提供一个字段,然后使用TreeCell显示该属性的字符串值的字段。

这是一个非常基本的例子:

import java.util.Arrays;
import java.util.List;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.stage.Stage;

public class TreeViewWithProperties extends Application {

    @Override
    public void start(Stage primaryStage) {
        List<SomeEntity> entities = Arrays.asList(
                new SomeEntity("First object", "String value 1", 42),
                new SomeEntity("Second object", "String value 2", 3)
        );

        TreeView<SomeEntity> tree = new TreeView<>();
        tree.setShowRoot(false);

        TreeItem<SomeEntity> treeRoot = new TreeItem<>();
        tree.setRoot(treeRoot);


        for (SomeEntity entity : entities) {
            TreeItem<SomeEntity> item = PropertyTreeItem.baseItem(entity);
            treeRoot.getChildren().add(item);

            item.getChildren().add(new PropertyTreeItem<String>(entity, entity.getStringField()));
            item.getChildren().add(new PropertyTreeItem<Integer>(entity, entity.getValue()));
        }

        tree.setCellFactory(tv -> new TreeCell<SomeEntity>() {
            @Override
            protected void updateItem(SomeEntity entity, boolean empty) {
                super.updateItem(entity, empty);
                PropertyTreeItem<?> item = (PropertyTreeItem<?>) getTreeItem();
                if (empty) {
                    setText(null);
                } else {
                    setText(item.getPropertyValue().toString());
                }
            }
        });

        Scene scene = new Scene(tree);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class PropertyTreeItem<T> extends TreeItem<SomeEntity> {

        private final T propertyValue ;

        public PropertyTreeItem(SomeEntity entity, T value) {
            super(entity);
            this.propertyValue = value ;
        }

        public static PropertyTreeItem<SomeEntity> baseItem(SomeEntity entity) {
            return new PropertyTreeItem<>(entity, entity);
        }

        public T getPropertyValue() {
            return propertyValue ;
        }
    }

    public class SomeEntity {

        private String name ;
        private String stringField ;
        private int value ;


        public SomeEntity(String name, String stringField, int value) {
            this.name = name;
            this.stringField = stringField;
            this.value = value;
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getStringField() {
            return stringField;
        }
        public void setStringField(String stringField) {
            this.stringField = stringField;
        }
        public int getValue() {
            return value;
        }
        public void setValue(int value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return name ;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

当然,对此进行一些变化是可能的。如果您想在实体类中使用 JavaFX 属性,并且能够在树外部更改这些值,您可以将文本绑定到单元格中的属性,而不是简单地设置它。

  • @KevinFurlong 那么也许你可以问这个问题,而不是你实际问的问题。 (4认同)