箭头是TreeCell的disclosureNode的一部分.如果未指定,则TreeCell的皮肤负责提供默认的显示节点(例如三角形).这由属性设定者文档说明:
The node to use as the “disclosure” triangle, or toggle, used for expanding and collapsing items. This is only used in the case of an item in the tree which contains child items. If not specified, the TreeCell’s Skin implementation is responsible for providing a default disclosure node.
但是,从TreeCellSkin看,它似乎没有提供默认的公开节点.相反,这似乎由TreeViewSkin处理(在JavaFX 8和JavaFX 11中).看一下实现,默认的公开节点是一个StackPane,其子StackPane充当实际的箭头.它们的样式类分别是tree-disclosure-node和arrow.请注意,这在任何地方都没有出现,包括JavaFX CSS Reference Guide.
在我看来,隐藏根公开节点的最简单,最不易出错的方法是使用CSS.这里唯一的问题是TreeCell无法提供仅以根单元为目标的方法.但这仍然可以通过将TreeCell子类化并提供我们自己的PseudoClass来实现.然后在TreeView上设置cellFactory.
要设置根的图形,请设置根TreeItem的TreeItem.graphic属性.
CustomTreeCell
import javafx.beans.InvalidationListener;
import javafx.css.PseudoClass;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeView;
import javafx.util.Callback;
public class CustomTreeCell extends TreeCell {
private static final PseudoClass ROOT = PseudoClass.getPseudoClass("root");
public static Callback, TreeCell> forTreeView() {
return treeView -> new CustomTreeCell<>();
}
public CustomTreeCell() {
getStyleClass().add("custom-tree-cell");
InvalidationListener listener = observable -> {
boolean isRoot = getTreeView() != null && getTreeItem() == getTreeView().getRoot();
pseudoClassStateChanged(ROOT, isRoot);
};
treeViewProperty().addListener(listener);
treeItemProperty().addListener(listener);
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
graphicProperty().unbind();
setGraphic(null);
} else {
setText(item.toString()); // Really only works if item is a String. Change as needed.
graphicProperty().bind(getTreeItem().graphicProperty());
}
}
}
CSS文件
.custom-tree-cell:root .tree-disclosure-node,
.custom-tree-cell:root .arrow {
-fx-min-width: 0;
-fx-pref-width: 0;
-fx-max-width: 0;
-fx-min-height: 0;
-fx-pref-height: 0;
-fx-max-height: 0;
}
/* Related to question asked in the comments by OP */
.custom-tree-cell > .tree-disclosure-node > .arrow {
-fx-shape: "M 0 0 L 10 5 L 0 10 L 0 8 L 8 5 L 0 2 Z";
}
一些注意事项:
>由于在单元实现中将TreeCell.graphic属性绑定到TreeItem.graphic属性,因此您将无法从CSS设置图形.您可以修改此设置以仅设置图形而不是绑定,以启用该功能.然后,您不必通过代码设置根TreeItem的图形,而是可以执行以下操作..custom-tree-cell:root {-fx-graphic:…; }.
>这不会删除显示节点,只是使其没有宽度和高度.
>此解决方案依赖于实施细节;更改JavaFX版本时要小心.我仅在JavaFX 11.0.2上尝试过此方法,但我相信它也应适用于JavaFX 8.