有深色背景和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);
TabMenuElement具有方法getIV以获取ImageView(图标),如果它是为此elemnt和getName定义以获取要显示的文本.现在它看起来像这样
所以我有以下问题:
>如何仅在TreeView中的所选项目上更改字体?
>如何在选定的子树上设置背景?
>如何强制最多可以扩展一个子树
>如何设置更大的尺寸到顶级项目?
解决方法
how to change font only on selected item in TreeView?
在你的css文件中,只需定义.tree-cell的字体:selected:
.tree-cell:selected { -fx-font-weight: bold ; }
how to setup background on selected sub-tree?
这个有点棘手.您希望任何扩展节点的背景以及父节点不是根节点的任何节点都不同(这不是您的措辞,但我认为它在逻辑上是等效的).扩展节点已经有一个CSS伪类.对于“父级不是根”,您需要定义自己的伪类:
PseudoClass subElementPseudoClass = PseudoClass.getPseudoClass("sub-tree-item");
现在观察单元格的treeItem属性,并在更改时更新伪类状态:
treeView.setCellFactory(tv -> { TreeCell<TabMenuElement> cell = new TreeCell<TabMenuElement>() { @Override public void updateItem(TabMenuElement 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 ; });
现在,您可以在CSS文件中执行此操作
.tree-cell:expanded,.tree-cell:sub-tree-item { -fx-background-color: ... ; }
how to force that at most one subtree could be expanded
将以下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.
how to set bigger size to top level items?
.tree-cell { -fx-padding: 0.75em 0em 0.75em 0em ; } .tree-cell:sub-tree-item { -fx-padding: 0.25em ; }
(或更改字体大小或类似内容.)
这是一个完整的例子:
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,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,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); } }
使用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 ; }