当前位置: 首页 > 知识库问答 >
问题:

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

贺聪
2023-03-14

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

当我直接在我的CellFactory中使用setTextFill()时,它工作正常,但我想使用外部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");
    }

}

样式表:

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

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

编辑:我使用CSS成功地应用了自定义文本颜色和背景颜色。我的实现现在使用包装在VBox中的标签,使背景色填充整个表格单元格。但是,在删除自定义样式时,我仍然存在一些背景色未清除的问题。

有没有比采用清晰的风格更好的解决方案?

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");
              }
           }
        }
     };
  }
});

我的样式表:

/** 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;
}

共有2个答案

轩辕弘雅
2023-03-14

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

这就是你正在做的:

@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);
    ...
}

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

如果您想要有一个红色文本的对象(在我的例子中是一个标签),请将样式表应用于该对象:

            @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);
                }
            }

编辑

这是示例的完整代码:

@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();

}

表中的位置。css:

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

运行此简短示例应如下所示:

朱保赫
2023-03-14

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

设置为图形的Label不会从表单元格继承-fx-text-填充的原因是Label还具有-fx-text-填充的设置。在默认样式表中,TableCellLabel都有如下设置:

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

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%
);

这个(相当复杂的)设置意味着-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-dar-text-Color-fx-mid-text-Color-fx-light-text-Color的值分别设置为黑色、深灰色(#333)和白色。

由于标签不会覆盖“fx text background color”(fx文本背景色)的值,因此只需更改表格单元格的值即可实现所需的功能:

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

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

执行此操作的更复杂的方法是重新定义-fx-[light|中|暗]-text-Colors。这样做的优点是,如果您更改背景,颜色会适当调整:特别是如果选择了单元格,您可以确保文本保持可见:

.styleImportant {
    -fx-light-text-color: white ;
    -fx-mid-text-color:   #c00 ;
    -fx-dark-text-color:  red ;
}
 类似资料:
  • 具有在样式中指定的默认textColor属性。xml应用主题: 如果可以使用样式上的这个新项在某些需要的情况下覆盖它,那将是完美的。xml文件: 并在所需的textview xml布局上指定它,如下所示: 问题是有些东西不起作用,因为自定义textview显示时使用的是自定义主题的默认颜色(白色),而不是在自定义样式中为该textview指定的自定义颜色(绿色)。 我做错了什么?

  • 任何人都可以解释如何使用(rgb值或十六进制值)将自定义颜色添加到excel工作表(在前景或背景中)使用Apche poi中的单元格样式添加到Excelsheet(XSSF工作簿)中?

  • 好。。。我在这里疯了。我已经开始尝试使用 SVG。使用 SVG 并对其应用 CSS 类就像一个魅力。我只是无法弄清楚我做错了什么,但我只是无法让类在svg文本元素上工作。我已经把它一直剥离了,这就是我得到的: 根据http://www.w3.org/TR/SVG/styling.html#ClassAttribute这应该行得通。。。 关于要更改的内容或替代方案的任何提示/提示?

  • 我在styles.xml中使用一个主题,如下所示: 我在AndroidManifest.xml中将其声明为Android:theme: 问题在下图中以红色突出显示。 感谢所有的答案!

  • 如何在Flutter中添加十六进制值的颜色?例如,我正在尝试以下操作: 提前致谢

  • 问题内容: 谁能解释使用Apche poi中的Cellstyle将Excel表格(前景值或背景值)(rgb值或十六进制值)添加到Excelsheet(XSSF工作簿)时如何自定义颜色? 问题答案: 设置自定义颜色取决于文件的类型(Office Open XML格式与BIFF格式)。由于弃用,使用不同版本的可能会有所不同。 使用Office Open XML格式,我们可以简单地使用XSSFColor