java JavaFX:使用自定义样式表将文本颜色应用于 TableCell?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26997008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 11:02:17  来源:igfitidea点击:

JavaFX: Apply text color to TableCell using custom style sheet?

javacssjavafxstylestableview

提问by user1438038

JavaFX: How can I apply text color to a TableCell using a custom style sheet?

JavaFX:如何使用自定义样式表将文本颜色应用于 TableCell?

It works fine, when I use setTextFill()in my CellFactory directly, but I want to apply custom style using an external CSS file. I could prove that my CSS class is applied, since the font becomes bold. The CSS file's font color, however, is not applied.

它工作正常,当我setTextFill()直接在我的 CellFactory 中使用时,但我想使用外部 CSS 文件应用自定义样式。我可以证明应用了我的 CSS 类,因为字体变为粗体。但是,不应用 CSS 文件的字体颜色。

@Override
protected void updateItem(MyObject item, boolean empty) {
    super.updateItem(item, empty);

    if (null != item) {        
        // EITHER:
        this.getStyleClass().add("styleImportant"); // Does NOT set color.

        // OR:
        this.setTextFill(Color.RED); // Does set color.
    }
    else {
        this.getStyleClass().remove("styleImportant");
    }

}

Style sheet:

样式表:

.styleImportant {
    -fx-font-weight: bold; /** Does work. */
    -fx-text-fill: red; /** Does NOT work. */
}

It is somehow related to specificity of CSS selectors, but I did not manage to find any valid setup.

它在某种程度上与 CSS 选择器的特异性有关,但我没有设法找到任何有效的设置。



Edit:I managed to apply both, a custom text color and background color, using CSS. My implementation now uses a Labelthat is wrapped in a VBoxto make the background color fill the entire table cell. However, I still had some issues with background color not being cleared when removing the custom style.

编辑:我设法使用 CSS 应用了自定义文本颜色和背景颜色。我的实现现在使用Label包裹在 a 中的 aVBox使背景颜色填充整个表格单元格。但是,在删除自定义样式时,我仍然遇到一些背景颜色没有被清除的问题。

Is there any better solution than applying a clear style?

有没有比应用清晰的样式更好的解决方案?

colExample.setCellFactory(new Callback<TableColumn<Example, Example>, TableCell<Example, Example>>() {
  @Override
  public TableCell<Example, Example> call(TableColumn<Example, Example> tableColumn) {
     return new TableCell<Example, Example>() {
        private VBox container;
        private Label text;

        // Anonymous constructor
        {
           this.container = new VBox();
           this.text = this.createLabel();

           this.container.getChildren().add(this.text);
           this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
           this.setStyle("-fx-padding: -1 -1 -1 -1;"); // Remove padding from cell

           this.setGraphic(this.container);
        }

        private final Label createLabel() {
           Label label = new Label();

           VBox.setVgrow(label, Priority.ALWAYS);
           label.setMaxWidth(Double.MAX_VALUE);
           label.setMaxHeight(Double.MAX_VALUE);
           label.setAlignment(Pos.CENTER);

           return label;
        }

        @Override
        protected void updateItem(Example example, boolean empty) {
           super.updateItem(example, empty);

           // Reset column styles
           if (null != this.text && null != this.text.getStyleClass()) {
              String[] possibleStyles = new String[] { "styleImportant", "clearStyle" };

              for (String style: possibleStyles) {
                 if (this.text.getStyleClass().contains(style)) {
                    // Will not reset background, even though style is removed?
                    this.text.getStyleClass().remove(style);
                 }
              }

              // Apply reset style to clear background color
              this.text.getStyleClass().add("clearStyle");
           }

           if (null != example) {
              this.text.setText(example.getContent());

              if (example.isImportant()) {
                 this.text.getStyleClass().add("styleImportant");
              }
           }
        }
     };
  }
});

My style sheet:

我的样式表:

/** Keep black text color, when user selects row */
.table-row-cell:focused {
   -fx-dark-text-color: #000000;
   -fx-mid-text-color: #000000;
   -fx-light-text-color: #000000;
}

/** Style to reset background color */
.clearStyle {
   -fx-background-color: transparent;
}

/** Style for important cells */
.styleImportant {
   /** Red text color on any background */
   -fx-dark-text-color: #FF0000;
   -fx-mid-text-color: #FF0000;
   -fx-light-text-color: #FF0000;

   -fx-background-color: #FF9999;
}

回答by James_D

As José points out in his answer, if you are setting a graphic in your cell, you (probably) need to apply the css style class to the graphic (depending on what that graphic is). If you are simply calling setText(...)your code should work.

正如何塞在他的回答中指出的那样,如果您在单元格中设置图形,则(可能)需要将 css 样式类应用于图形(取决于该图形是什么)。如果您只是调用setText(...)您的代码应该可以工作。

The reason that a Labelset as the graphic doesn't inherit -fx-text-fillfrom the table cell is that the Labelalso has a setting for -fx-text-fill. In the default stylesheet, both TableCelland Labelhave this set as follows:

Label作为图形的集合不-fx-text-fill从表格单元格继承的原因是它Label也有一个设置为-fx-text-fill. 在默认样式表中,TableCellLabel都具有如下设置:

-fx-text-fill: -fx-text-background-color ;

fx-text-background-coloris a looked-up colorthat is defined as a ladder, as follows:

fx-text-background-color是定义为阶梯的查找颜色,如下所示:

-fx-text-background-color: ladder(
    -fx-background,
    -fx-light-text-color 45%,
    -fx-dark-text-color  46%,
    -fx-dark-text-color  59%,
    -fx-mid-text-color   60%
);

This (fairly complex) setting means that the value of -fx-text-background-colordepends on the value of -fx-background. If -fx-backgroundis less than 45% of maximum intensity (i.e. it's dark), the value of -fx-text-background-coloris set to -fx-light-text-color. If -fx-backgroundis between 46% and 59% intensity, the value is equal to -fx-drak-text-color. If it is 60% or more, it's set to -fx-mid-text-color. The idea here is that the text color will automatically adjust to the background to remain visible. The values of -fx-dark-text-color, -fx-mid-text-color, and -fx-light-text-colorare set to black, a dark gray (#333), and white, respectively.

这个(相当复杂的)设置意味着 的值-fx-text-background-color取决于 的值-fx-background。如果-fx-background小于最大强度的 45%(即它是暗的),则将 的值-fx-text-background-color设置为-fx-light-text-color。如果-fx-background强度介于 46% 和 59% 之间,则该值等于-fx-drak-text-color。如果是 60% 或更多,则设置为-fx-mid-text-color。这里的想法是文本颜色会自动调整到背景以保持可见。的值-fx-dark-text-color-fx-mid-text-color-fx-light-text-color分别被暗灰色(#333),和白色,设置为黑色。

Since Labeldoes not override the value of -fx-text-background-color, you can achieve what you need by just changing the value of that for your table cell:

由于Label不会覆盖 的值-fx-text-background-color,您只需更改表格单元格的值即可实现所需的内容:

.styleImportant {
    -fx-text-background-color: red ;
}

Now this overrides the looked-up color value for the table cell, and since the graphic inside the cell doesn't override that value itself, it inherits it from the cell.

现在这会覆盖表格单元格的查找颜色值,并且由于单元格内的图形不会覆盖该值本身,它从单元格继承它。

A more sophisticated way to do this is to redefine the -fx-[light|mid|dark]-text-colors. The advantage of this is that the colors will adjust appropriately if you change the background: in particular if the cell is selected you can ensure that the text stays visible:

一种更复杂的方法是重新定义-fx-[light|mid|dark]-text-colors。这样做的好处是,如果您更改背景,颜色会适当调整:特别是如果选中了单元格,您可以确保文本保持可见:

.styleImportant {
    -fx-light-text-color: white ;
    -fx-mid-text-color:   #c00 ;
    -fx-dark-text-color:  red ;
}

回答by José Pereda

Since I don't know what type of object is in the cell, I'll use a Label.

由于我不知道单元格中是什么类型的对象,因此我将使用Label.

This is what you are doing:

这就是你在做什么:

@Override
public void start(Stage primaryStage) {
    TableView<Label> table = new TableView<>();
    TableColumn<Label,String> column = new TableColumn<>();
    column.setCellValueFactory(param -> param.getValue().textProperty());
    column.setCellFactory((TableColumn<Label, String> param) -> {
        TableCell<Label, String> cell = new TableCell<Label, String>(){

            @Override
            protected void updateItem(String item, boolean empty){
                super.updateItem(item, empty);
                if(!empty){
                    this.getStyleClass().add("styleImportant");
                    Label label = new Label(item);
                    setGraphic(label);
                }
            }
        };
        return cell;
    });
    table.getColumns().add(column);
    ...
}

This will give you bold text, but black.

这将为您提供粗体文本,但为黑色。

If you want to have an object (in my case, a Label) with red text, apply the style sheet to the object:

如果您想要一个Label带有红色文本的对象(在我的情况下是 a ),请将样式表应用于该对象:

            @Override
            protected void updateItem(String item, boolean empty){
                super.updateItem(item, empty);
                if(!empty){
                    Label label = new Label(item);
                    label.getStyleClass().add("styleImportant");
                    setGraphic(label);
                }
            }

EDIT

编辑

This is the full code of the example:

这是示例的完整代码:

@Override
public void start(Stage primaryStage) {
    TableView<Label> table = new TableView<>();

    ObservableList<Label> data = FXCollections.observableArrayList(
             new Label("Some Text"), new Label("Some More Text"));

    TableColumn<Label,String> column = new TableColumn<>("Column");
    column.setCellValueFactory(param -> param.getValue().textProperty());
    column.setCellFactory((TableColumn<Label, String> param) -> {
        TableCell<Label, String> cell = new TableCell<Label, String>(){

            @Override
            protected void updateItem(String value, boolean empty){
                super.updateItem(value, empty);

                if(!empty){
                    Label label = new Label(value);
                    label.getStyleClass().add("styleImportant");
                    setGraphic(label);
                } else {
                    setGraphic(null);
                } 
            }
        };
        return cell;
    });
    column.setPrefWidth(100);
    table.getColumns().add(column);

    table.setItems(data);

    Scene scene = new Scene(table, 300, 250);
    scene.getStylesheets().add(getClass().getResource("table.css").toExternalForm());
    primaryStage.setScene(scene);
    primaryStage.show();

}

where in table.css:

在 table.css 中的位置:

.styleImportant {
    -fx-font-weight: bold;
    -fx-text-fill: red;
}

Running this short sample should look like this:

运行这个简短的示例应该如下所示:

Styled label

样式标签