JavaFX-CSS:如何将父母的风格“移动”给孩子?

触发这个是一个快速实验来解决TreeItem选择宽度 :要求是仅突出显示文本,而不是整个树单元格。 没有比那更容易的事了(弗雷德里克说:)

  • 使用Label作为图形实现自定义TreeCell(并根据需要使用项目配置标签)
  • 删除选择样式(主要是单元格中的高亮背景)
  • 将高亮样式添加到标签中

类似的东西(使用它的可运行的例子在最后):

public static class MyTreeCell extends TreeCell { private Label label; public MyTreeCell() { getStyleClass().add("tree-text-only"); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (label == null) { label = new Label(); } label.setText(item); setGraphic(label); } } } 

css:

 /* remove the highlight from cell as a whole, c&p'd the unselected style from modena */ .tree-text-only:filled:selected { -fx-background: -fx-control-inner-background; -fx-background-color: -fx-background; } /* c&p'd selected style */ /* using > doesn't make a different to the behaviour */ /* .tree-text-only:filled:selected > .label { */ .tree-text-only:filled:selected .label { /* following is the selection color from themes, doesn't show */ -fx-background: -fx-selection-bar; /* hard-coded color does show */ /* -fx-background-color: -fx-accent ; */ /* auto-adjust text fill */ /* no effect for hard-coded color, showing nothing for selection bar */ -fx-text-fill: -fx-text-background-color; } 

预期的行为

  • 使用选择栏时,标签突出显示背景
  • 文本自动调整其填充

实际行为:

  • 使用“语义”(?)高亮颜色选择栏,标签的背景颜色不会更改为高亮颜色,但文本填充更改为“白色”,因此文本不显示
  • 使用硬编码颜色(任何,甚至上面的重音)都会更改标签的背景,但文本填充不会更新

显而易见的问题:如何使其按预期工作?

为方便起见,一个可运行的例子:

 public class TreeCellExample extends Application { public static class MyTreeCell extends TreeCell { private Label label; public MyTreeCell() { getStyleClass().add("tree-text-only"); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (label == null) { label = new Label(); } label.setText(item); setGraphic(label); } } } private Parent getContent() { TreeItem root = createSubTree("root"); root.setExpanded(true); TreeView tree = new TreeView(root); tree.getStylesheets().add( getClass().getResource("treetextonly.css").toExternalForm()); tree.setCellFactory(p -> new MyTreeCell()); BorderPane pane = new BorderPane(tree); return pane; } ObservableList rawItems = FXCollections.observableArrayList( "9-item", "8-item", "7-item", "6-item", "5-item", "4-item", "3-item", "2-item", "1-item"); protected TreeItem createSubTree(Object value) { TreeItem child = new TreeItem(value); child.getChildren().setAll((List) rawItems.stream() .map(TreeItem::new) .collect(Collectors.toList())); return child; } @Override public void start(Stage primaryStage) throws Exception { Scene scene = new Scene(getContent()); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

它不起作用的原因是因为.label没有应用-fx-background的规则,因此分配给它的任何值都不会影响任何Label属性。

更重要的是, Label不使用-fx-background-color属性。

所以一个简单的解决方案是添加它:

 .tree-text-only > .label { -fx-background-color: -fx-background; } 

现在,您可以仅使用此“语义”颜色应用所有样式。

注意我还添加了控件没有焦点的情况:

 /* * remove the highlight from cell as a whole */ /* Selected rows */ .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:filled:selected { -fx-background: -fx-control-inner-background; } /* Selected when control is not focused */ .tree-text-only:filled:selected { -fx-background: -fx-control-inner-background; } /* focused cell (keyboard navigation) */ .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:focused { -fx-cell-focus-inner-border: -fx-control-inner-background; } /* * highlight only the label */ // Add background color rule .tree-text-only > .label { -fx-background-color: -fx-background; } /* Selected rows */ .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:filled:selected > .label { -fx-background: -fx-selection-bar; } /* Selected when control is not focused */ .tree-text-only:filled:selected > .label { -fx-background: -fx-selection-bar-non-focused; } /* focused cell (keyboard navigation) */ .tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-text-only:focused > .label { -fx-background: -fx-selection-bar; } 

同样,我不是100%确定我理解您的要求,但是对我进行快速测试后( Label被分配给Button的图形属性):

 .button { -fx-text-fill: red; -fx-background-color: yellow; } .button > .label { -fx-text-fill: blue; -fx-background-color: yellow; } .button:pressed > .label { -fx-text-fill: white; -fx-background-color: black; }