是否可以在树视图中隐藏节点(与Root的工作方式相同),而不必从树本身中删除节点?目的是能够在树的某个项目上提供过滤器和“显示/隐藏”选项。
所有帮助表示赞赏
由于
答案 0 :(得分:4)
我发现Christoph Keimel的这个article,我认为应该解决你的问题。
基本上你没有黑客就无法做到。 您可以使用FilterableTreeItem扩展TreeItem,您可以在其中创建FilteredList。
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);
}
}
您还需要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);
}
你把它放在你的控制器
中 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));
hide是一个SimpleBooleanProperty。我的节点有一个布尔属性样式。
private final BooleanProperty hide = new SimpleBooleanProperty();
代码只允许隐藏明显的节点或没有样式的节点。 我知道这很愚蠢,但我刚做了一个测试
答案 1 :(得分:1)
您无法将单元格visibleProprerty
绑定到外部布尔属性,因为VirtualFlow
将自行管理单元格,并在需要时将其可见性设置为true,而不管您的设置如何。“ / p>
作为替代方法,您可以禁用单元格,或者通过将其不透明度设置为0来使其不可见,但单元格的大小将存在空白。
这个answer向您展示了如何禁用单个单元格。要更改不透明度,只需向opacityProperty
类添加Wrap
,或创建绑定:
// disable cell
cell.disableProperty().bind(wrap.disabledProperty());
// or "hide" cell with blank gap
// - with new property in Wrap
cell.opacityProperty().bind(wrap.opacityProperty());
// - with a Binding
cell.opacityProperty().bind(
Bindings.createDoubleBinding(()->wrap.disabledProperty().get()?0d:1d,
wrap.disabledProperty()));