【问题标题】:Automatically Updating TreeView of Nested Items自动更新嵌套项的 TreeView
【发布时间】:2014-09-04 01:41:37
【问题描述】:

我有一个目标,其中有一个目标列表。一个目标有一个策略列表。战略有一个战术列表。一个策略有一个任务列表。

我希望能够在 TreeView 中显示它,并且我希望树与项目同步。也就是说,如果我删除了一个目标,那么该目标及其子项也会从 TreeView 中消失。

到目前为止,这是我一直在尝试的。

/**
 * The base class for all PlanItems, which include ActionItems down to
 * ActionTasks, and Objectives down to Tasks.
 *
 * @author Toni-Tran
 */
public class PlanItem implements Comparable<PlanItem> {
    protected ObservableList<PlanItem> childPlanItems = FXCollections
            .observableArrayList();
    protected TreeItem<PlanItem> treeItem = new TreeItem<>(this);

这是所有这些项目的基类。在其构造函数中:

public PlanItem() {
    CustomBinding.bindLists(treeItem.getChildren(), childPlanItems, PlanItem::getTreeItem);
}

我正在使用我的自定义绑定,它将两个不同对象的列表绑定在一起。 (或者,我可以使用 EasyBind)。

/**
 * Binds a source list's elements to a destination list. Any changes made in
 * the source list will reflect in the destination list.
 *
 * @param <SRC> The source list's object type.
 * @param <DEST> The destination list's object type.
 * @param dest The destination list that will be bound to the src list.
 * @param src The source list to watch for changes, and propagate up to the
 * destination list.
 * @param transformer A function that will transform a source list data
 * type, A, into a destination list data type, B.
 */
public static <SRC extends Object, DEST extends Object> void bindLists(
        ObservableList<DEST> dest, ObservableList<SRC> src, Function<SRC, DEST> transformer) {
    /*Add the initial data into the destination list.*/
    for (SRC a : src) {
        dest.add(transformer.apply(a));
    }
    /*Watch for future data to add to the destination list. Also watch for removal
     of data form the source list to remove its respective item in the destination
     list.*/
    src.addListener((ListChangeListener.Change<? extends SRC> c) -> {
        while (c.next()) {
            /*Watch for removed data.*/
            if (c.wasRemoved()) {
                for (SRC a : c.getRemoved()) {
                    int from = c.getFrom();
                    dest.remove(from);
                }
            }
            /*Watch for added data.*/
            if (c.wasAdded()) {
                for (SRC a : c.getAddedSubList()) {
                    int indexAdded = src.indexOf(a);
                    dest.add(indexAdded, transformer.apply(a));
                }
            }
        }
    });
}

我不确定这是否是正确的方法。子项列表通常是扩展 PlanItem 的对象列表,而不仅仅是 PlanItem 本身。那不应该是ObservableList&lt;? extends PlanItem&gt;吗?这样做会使我的其余代码变得复杂。

计划是创建一个包装 PlanItem 的 TreeItem。然后,将 TreeItem 的子 TreeItems 同步到 PlanItem 的子 PlanItems。这也对每个嵌套的 PlanItem 递归重复。

【问题讨论】:

    标签: java inheritance javafx treeview javafx-8


    【解决方案1】:

    您的bindLists 方法非常通用,可以编写(就像您现在拥有的那样)而无需参考您现在正在使用的列表(即不参考PlanItem 类)。所以我可能会成功

    public static <SRC, DEST> void bindLists(ObservableList<DEST> dest, ObservableList<SRC> src, ...) { ... }
    

    请注意,尽管映射函数必须能够应用于 src 的元素(因此它必须作用于 src 的元素是一种类型的事物)并产生可以放置的事物进入dest 列表。所以使用Function&lt;SRC, DEST&gt; 可能过于严格。试试

    public static <SRC, DEST> void bindLists(ObservableList<DEST> dest, ObservableList<SRC> src, 
         Function<? super SRC, ? extends DEST> transformer) { ... }
    

    现在你可以打电话了

    bindLists(ObservableList<TreeItem<PlanItem>>, ObservableList<T>, PlanItem::getTreeItem)
    

    其中TPlanItem或任何子类,它应该易于使用。

    【讨论】:

    • 为什么我必须给函数参数一个下限?为什么不扩展?
    • 你真正想要传入的函数是 Function&lt;PlanItem, TreeItem&lt;PlanItem&gt;&gt;(因为你在 PlanItem 类中定义它,采用 this -&gt; new TreeItem&lt;&gt;(...)。)如果这是对一个元素起作用,比如说ObservableList&lt;Goal&gt; 的参数类型(PlanItem)是你给它的实际值的超类(Goal)...列表的元素必须是可分配给 函数的类型。函数的返回类型必须分配给目标列表的类型,因此您在此处使用extends
    • Function&lt;? super SRC, ? extends DEST&gt; 。我理解函数的第二个参数。我们正在尝试将DEST(和DEST 的子类)对象插入List&lt;DEST&gt;。但是我对第一个参数仍然有些困惑。源列表可以是List&lt;Goal&gt;List&lt;Strategy&gt; 或其他。当前SRC 的这两个超类怎么样?如果我看起来很愚蠢,我很抱歉,我只是对通用界限很糟糕。 :(
    • 哦,等等,我想我明白了。该函数将采用本身或自身超类型的任何内容。例如,它将采用Goal,但也将采用PlanItem。然后将其转换为DEST 对象或DEST 的子类,然后将其添加到List&lt;DEST&gt;。我说的对吗?
    猜你喜欢
    • 2013-05-12
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 2020-10-22
    • 2012-11-16
    • 2011-04-14
    相关资源
    最近更新 更多