我发现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节点或未设置样式的节点。我知道这很愚蠢,但我只是做了一个测试