如何将域对象绑定到JavaFX TreeView?

Rob*_*ert 5 model-view-controller javafx

如何将域对象绑定到JavaFX TreeView?ComboBox有getItems(),你可以添加一些东西到该集合.TreeView似乎没有这样的方法.我只能通过将TreeItems添加到TreeView的根目录然后使用getChildren().add(...)添加子项来手动构建树,但似乎没有办法只添加可观察的树结构.

域对象可以从文件中读取自身并将自身写入文件.它有修改其内容的方法.如何最好地将其与TreeView挂钩,以便用户可以添加和删除节点?

我不想在我的域对象中使用GUI代码(即JavaFX类).

我是否需要编写一个可以将我的域对象转换为JavaFX树的Adapter类?然后将监听器添加到树中并将更改映射回域对象?或者,还有更好的方法?

Man*_*uky 6

前段时间我遇到了类似的问题.我编写了一个TreeItem可以处理递归数据结构的自定义实现.我写了一个博客帖子有详细的解释在这里.

RecursiveTreeItem的代码可以作为gist找到.

作为一个例子,想一个Task可以包含许多子任务的类等等.

public class Task {
    private ObservableList<Task> subtasks = FXCollections.observableArrayList();

    public ObservableList<Task> getSubtasks() {
        return subtasks;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以按如下方式使用它:

Task root = new Task();
TreeItem<Task> rootItem = new RecursiveTreeItem<Task>(root, Task::getSubtasks); 
tree.setRoot(rootItem);
Run Code Online (Sandbox Code Playgroud)

第二个参数是类型Callback<T, ObservableList<T>>:一个函数,它接受T(在我们的例子中Task)的元素并返回该元素的子元素.在示例中,我使用方法引用作为快捷方式.

这是一个完全被动的实现,即当添加一个新子项时,它将立即显示在TreeView中.

你说你不喜欢你的域模型中有JavaFX类.在这种情况下,你可以写这样的东西(未经测试):

TreeItem<Task> rootItem = new RecursiveTreeItem<Task>(root, 
    task -> FXCollections.observableArrayList(task.getSubtasks()));
Run Code Online (Sandbox Code Playgroud)

这里getSubtasks()返回一个List<Task>包含在observableList中的plain .但在这种情况下,TreeView不会在模型更改时自动更新.