我想创建元素外观和行为,如下所示.

有深色背景和4个元素的顶部列表:"biblioteki","Analiza"等.当我们点击其中一个列表时,列表会被展开,这个项目及其子项会变得很暗.来自子列表的Additionaly选择项目获得不同的字体(粗体和白色).此外,当时只有一个项目可以扩展.
所以我发现这是应用了适当样式的TreeView行为.我使用以下代码:
TreeView<TabMenuElement> treeView = new TreeView<>(treeRoot);
treeView.setCellFactory(tv -> new TreeCell<TabMenuElement>() {
@Override
public void updateItem(TabMenuElement item, boolean empty) {
super.updateItem(item, empty);
setDisclosureNode(null);
if (empty) {
setText("");
setGraphic(null);
} else {
setText(item.getName()); // appropriate text for item
if (item.getIv() != null) {
setGraphic(item.getIv());
}
}
}
});
treeView.setShowRoot(false);
Run Code Online (Sandbox Code Playgroud)
TabMenuElement具有方法getIV以获取ImageView(图标),如果它是为此elemnt和getName定义以获取要显示的文本.现在它看起来像这样

所以我有以下问题:
Jam*_*s_D 13
如何仅在TreeView中的选定项目上更改字体?
在您的css文件中,只需定义以下字体.tree-cell:selected:
.tree-cell:selected {
-fx-font-weight: bold ;
}
Run Code Online (Sandbox Code Playgroud)
如何在选定的子树上设置背景?
这个有点棘手.您希望任何扩展节点的背景以及父节点不是根节点的任何节点都不同(这不是您的措辞,但我认为它在逻辑上是等效的).扩展节点已经有一个CSS伪类.对于"父级不是根",您需要定义自己的伪类:
PseudoClass subElementPseudoClass = PseudoClass.getPseudoClass("sub-tree-item");
Run Code Online (Sandbox Code Playgroud)
现在观察treeItem单元格的属性,并在更改时更新伪类状态:
treeView.setCellFactory(tv -> {
TreeCell<TabMenuElement> cell = new TreeCell<TabMenuElement>() {
@Override
public void updateItem(TabMenuElement item, boolean empty) {
super.updateItem(item, empty);
setDisclosureNode(null);
if (empty) {
setText("");
setGraphic(null);
} else {
setText(item.getName()); // appropriate text for item
if (item.getIv() != null) {
setGraphic(item.getIv());
}
}
}
};
cell.treeItemProperty().addListener((obs, oldTreeItem, newTreeItem) -> {
cell.pseudoClassStateChanged(subElementPseudoClass,
newTreeItem != null && newTreeItem.getParent() != cell.getTreeView().getRoot());
}
return cell ;
});
Run Code Online (Sandbox Code Playgroud)
现在,您可以在CSS文件中执行此操作
.tree-cell:expanded, .tree-cell:sub-tree-item {
-fx-background-color: ... ;
}
Run Code Online (Sandbox Code Playgroud)
如何强制最多可以扩展一个子树
将以下内容添加ChangeListener到每个TreeItem扩展属性中:
ChangeListener<Boolean> expandedListener = (obs, wasExpanded, isNowExpanded) -> {
if (isNowExpanded) {
ReadOnlyProperty<?> expandedProperty = (ReadOnlyProperty<?>) obs ;
Object itemThatWasJustExpanded = expandedProperty.getBean();
for (TreeItem<TabMenuElement> item : treeView.getRoot().getChildren()) {
if (item != itemThatWasJustExpanded) {
item.setExpanded(false);
}
}
}
};
TreeItem<TabMenuElement> biblioteka = new TreeItem<>(...);
biblioteka.expandedProperty().addListener(expandedListener);
TreeItem<TabMenuElement> analiza = new TreeItem<>(...);
analiza.expandedProperty().addListener(expandedListener);
// etc, for all "top-level" items.
Run Code Online (Sandbox Code Playgroud)
如何设置更大的尺寸到顶级项目?
.tree-cell {
-fx-padding: 0.75em 0em 0.75em 0em ;
}
.tree-cell:sub-tree-item {
-fx-padding: 0.25em ;
}
Run Code Online (Sandbox Code Playgroud)
(或更改字体大小或类似内容.)
这是一个完整的例子:
import javafx.application.Application;
import javafx.beans.property.ReadOnlyProperty;
import javafx.beans.value.ChangeListener;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class StyledUniqueExpandingTree extends Application {
@Override
public void start(Stage primaryStage) {
TreeView<String> tree = new TreeView<>();
tree.setShowRoot(false);
TreeItem<String> root = new TreeItem<>("");
tree.setRoot(root);
ChangeListener<Boolean> expandedListener = (obs, wasExpanded, isNowExpanded) -> {
if (isNowExpanded) {
ReadOnlyProperty<?> expandedProperty = (ReadOnlyProperty<?>) obs ;
Object itemThatWasJustExpanded = expandedProperty.getBean();
for (TreeItem<String> item : tree.getRoot().getChildren()) {
if (item != itemThatWasJustExpanded) {
item.setExpanded(false);
}
}
}
};
for (int i=1; i<=4; i++) {
TreeItem<String> item = new TreeItem<>("Top level "+i);
item.expandedProperty().addListener(expandedListener);
root.getChildren().add(item);
for (int j=1; j<=4; j++) {
TreeItem<String> subItem = new TreeItem<>("Sub item "+i+":"+j);
item.getChildren().add(subItem);
}
}
PseudoClass subElementPseudoClass = PseudoClass.getPseudoClass("sub-tree-item");
tree.setCellFactory(tv -> {
TreeCell<String> cell = new TreeCell<String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setDisclosureNode(null);
if (empty) {
setText("");
setGraphic(null);
} else {
setText(item); // appropriate text for item
}
}
};
cell.treeItemProperty().addListener((obs, oldTreeItem, newTreeItem) -> {
cell.pseudoClassStateChanged(subElementPseudoClass,
newTreeItem != null && newTreeItem.getParent() != cell.getTreeView().getRoot());
});
return cell ;
});
BorderPane uiRoot = new BorderPane(tree);
Scene scene = new Scene(uiRoot, 250, 400);
scene.getStylesheets().add("styled-unique-expanded-tree.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
使用styled-unique-expanded-tree.css:
.tree-view, .tree-cell {
-fx-background-color: black ;
-fx-text-fill: white ;
}
.tree-cell:expanded, .tree-cell:sub-tree-item {
-fx-background-color: #404040 ;
}
.tree-cell:selected {
-fx-font-weight: bold ;
}
.tree-cell {
-fx-padding: 0.75em 0em 0.75em 0em ;
}
.tree-cell:sub-tree-item {
-fx-padding: 0.25em ;
}
Run Code Online (Sandbox Code Playgroud)