JavaFX-CSS:如何 "move" 父子样式?
JavaFX-CSS: How to "move" style of parent to a child?
触发这个问题的是一个快速实验来解决TreeItem selection width:要求是只突出显示文本,而不是整个树单元格。没有比这更容易的了(弗雷德里克说 :)
- 使用 Label 作为图形实现自定义 TreeCell(并根据需要使用项目配置标签)
- 删除选择样式(主要是单元格的高亮背景
- 给标签添加高亮样式
类似于(使用它的可运行示例在最后):
public static class MyTreeCell extends TreeCell<String> {
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;
}
预期行为
- 标签在使用选择栏时突出显示了背景
- 文本自动调整其填充
实际行为:
- 使用 "semantic" (?) 高亮颜色选择栏,标签的背景颜色没有更改为高亮颜色,但文本填充更改为 "white",因此文本不显示
- 使用硬编码颜色(任何颜色,甚至是上面的重音)会更改标签的背景,但不会更新文本填充
显而易见的问题:如何使其按预期工作?
为方便起见,一个可运行的例子:
public class TreeCellExample extends Application {
public static class MyTreeCell extends TreeCell<String> {
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<TreeItem>) 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);
}
}
同样,我不是 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;
}
它不起作用的原因是因为 .label
没有应用 -fx-background
的规则,因此分配给它的任何值都不会影响任何 Label
属性。
此外,Label
不使用 -fx-background-color
属性。
所以一个简单的解决方案是添加它:
.tree-text-only > .label {
-fx-background-color: -fx-background;
}
现在您可以仅使用这种 "semantic" 颜色应用所有样式。
注意我还添加了控件没有焦点的情况:
/*
* 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;
}
触发这个问题的是一个快速实验来解决TreeItem selection width:要求是只突出显示文本,而不是整个树单元格。没有比这更容易的了(弗雷德里克说 :)
- 使用 Label 作为图形实现自定义 TreeCell(并根据需要使用项目配置标签)
- 删除选择样式(主要是单元格的高亮背景
- 给标签添加高亮样式
类似于(使用它的可运行示例在最后):
public static class MyTreeCell extends TreeCell<String> {
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;
}
预期行为
- 标签在使用选择栏时突出显示了背景
- 文本自动调整其填充
实际行为:
- 使用 "semantic" (?) 高亮颜色选择栏,标签的背景颜色没有更改为高亮颜色,但文本填充更改为 "white",因此文本不显示
- 使用硬编码颜色(任何颜色,甚至是上面的重音)会更改标签的背景,但不会更新文本填充
显而易见的问题:如何使其按预期工作?
为方便起见,一个可运行的例子:
public class TreeCellExample extends Application {
public static class MyTreeCell extends TreeCell<String> {
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<TreeItem>) 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);
}
}
同样,我不是 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;
}
它不起作用的原因是因为 .label
没有应用 -fx-background
的规则,因此分配给它的任何值都不会影响任何 Label
属性。
此外,Label
不使用 -fx-background-color
属性。
所以一个简单的解决方案是添加它:
.tree-text-only > .label {
-fx-background-color: -fx-background;
}
现在您可以仅使用这种 "semantic" 颜色应用所有样式。
注意我还添加了控件没有焦点的情况:
/*
* 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;
}