TreeView Java FX:隐藏节点

Bla*_*dor 1 java treeview javafx java-8

是否可以在树视图中隐藏节点(对Root起作用的方式相同)而不必从树本身中删除节点?目的是能够在树的某些项目上提供过滤器和“显示/隐藏”选项。

所有帮助表示赞赏

谢谢

fan*_*fan 6

我发现Christoph Keimel撰写的这篇文章可以解决您的问题。

基本上,没有黑客就无法做到。您可以有一个FilterableTreeItem,它扩展了在其中创建FilteredList的TreeItem。

public class FilterableTreeItem<T> extends TreeItem<T> {
private final ObservableList<TreeItem<T>> sourceList;

private final ObjectProperty<TreeItemPredicate<T>> predicate = new SimpleObjectProperty<>();

public FilterableTreeItem(T value) {
    super(value);
    sourceList = FXCollections.observableArrayList();
    FilteredList<TreeItem<T>> filteredList = new FilteredList<>(sourceList);

    filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> {
        return child -> {
            // Set the predicate of child items to force filtering
            if (child instanceof FilterableTreeItem) {
                FilterableTreeItem<T> filterableChild = (FilterableTreeItem<T>) child;
                filterableChild.setPredicate(predicate.get());
            }
            // If there is no predicate, keep this tree item
            if (predicate.get() == null) {
                return true;
            }
            // If there are children, keep this tree item
            if (!child.getChildren().isEmpty()) {
                return true;
            }
            // Otherwise ask the TreeItemPredicate
            return predicate.get().test(this, child.getValue());
        };
    }, predicate));

    setHiddenFieldChildren(filteredList);
}

/**
 * Set the hidden private field {@link TreeItem#children} through reflection and hook the hidden {@link ListChangeListener} in {@link TreeItem#childrenListener} to the list
 * 
 */
protected void setHiddenFieldChildren(ObservableList<TreeItem<T>> list) {
    Field children = ReflectionUtils.findField(getClass(), "children");
    children.setAccessible(true);
    ReflectionUtils.setField(children, this, list);

    Field childrenListener1 = ReflectionUtils.findField(getClass(), "childrenListener");
    childrenListener1.setAccessible(true);
    Object childrenListener = ReflectionUtils.getField(childrenListener1, this);

    list.addListener((ListChangeListener<? super TreeItem<T>>) childrenListener);
}

/**
 * Returns the list of children that is backing the filtered list.
 * 
 * @return underlying list of children
 */
public ObservableList<TreeItem<T>> getInternalChildren() {
    return sourceList;
}

public final ObjectProperty<TreeItemPredicate<T>> predicateProperty() {
    return predicate;
}

public final TreeItemPredicate<T> getPredicate() {
    return predicate.get();
}

public final void setPredicate(TreeItemPredicate<T> predicate) {
    this.predicate.set(predicate);
}
Run Code Online (Sandbox Code Playgroud)

}

您还将需要TreeItemPredicate

@FunctionalInterface
public interface TreeItemPredicate<T> {
/**
 * Utility method to create a TreeItemPredicate from a given {@link Predicate}
 */
static <T> TreeItemPredicate<T> create(Predicate<T> predicate) {
    return (parent, value) -> predicate.test(value);
}

/**
 * Evaluates this predicate on the given argument.
 *
 * @param parent
 *            the parent tree item of the element or null if there is no
 *            parent
 * @param value
 *            the value to be tested
 * @return {@code true} if the input argument matches the
 *         predicate,otherwise {@code false}
 */
boolean test(TreeItem<T> parent, T value);
}
Run Code Online (Sandbox Code Playgroud)

然后将其放到Controller中

            MyNode myRootNode = myService.getTreeRootNode();

        FilterableTreeItem<MyNode> rootItem = new FilterableTreeItem<>(myRootNode);
        rootItem.setExpanded(true);

        for (MyNode node : myRootNode.getChildren()) {
            FilterableTreeItem<MyNode> item = new FilterableTreeItem<>(node);
            rootItem.getInternalChildren().add(item);
        }


        tree.setRoot(rootItem);


        rootItem.predicateProperty().bind(Bindings.createObjectBinding(()
                -> TreeItemPredicate.<MyNode> create(myNode
                        -> myNode.isStyled() == hide.getValue())
                , hide));
Run Code Online (Sandbox Code Playgroud)

hide是一个SimpleBooleanProperty。我的节点具有样式为boolean的属性。

private final BooleanProperty hide = new SimpleBooleanProperty();
Run Code Online (Sandbox Code Playgroud)

该代码仅允许隐藏stly节点或未设置样式的节点。我知道这很愚蠢,但我只是做了一个测试