如何在没有 CSS 的情况下更改列 header 的字体

How to change the font of a column header without CSS

我希望能够在不使用 CSS 的情况下为 JavaFX 的 TableView 更改列 header 的字体。我在网上查了很多,所有的解决方案似乎都只使用CSS。我要更改的字体是自定义字体,在 CSS 中为 JavaFX 加载自定义字体会出现一个错误,在搜索了数十个链接后我似乎无法修复。

我尝试的CSS方法是

@font-face {
    font-family: '8bitoperator';
    src: url('assets/8bitoperator.ttf');
}

.table-view .column-header.foo .label {
    -fx-text-fill: white;
    -fx-font-size: 0.13%; /* arbitrary value */
    -fx-font-family: '8bitoperator';
}

这会遇到 loadStylesheetUnPrivileged 错误。我程序中的所有其他样式都是通过 Javafx 而不是 CSS,所以我想保持它。

感谢任何帮助。

我不确定您当前的样式表问题。但是,如果您正在寻找一种以编程方式更新列 header 字体的方法,下面是一种方法。话虽如此,还有许多其他方法。

大意是:你想要的节点,不能通过任何一般API访问。所以我们在 table 视图完全呈现时查找节点。节点的“needsLayout”属性 将在完全呈现时变为 false。因此,如果您多次依赖 属性 和额外的 属性 而不是 运行,则可以使用“lookupAll”方法获得您的要求。

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.util.concurrent.atomic.AtomicBoolean;

public class ColumnHeaderCustomFontDemo extends Application {
    boolean fontsLoaded = false;

    int i = 1;

    @Override
    public void start(Stage primaryStage) throws Exception {
        TableView<Person> tableView = new TableView<>();
        TableColumn<Person, String> fnCol = new TableColumn<>("First Name");
        fnCol.setPrefWidth(120);
        fnCol.setId("firstColumn");
        TableColumn<Person, String> lnCol = new TableColumn<>("Last Name");
        lnCol.setId("lastColumn");
        lnCol.setVisible(false);
        TableColumn<Person, String> cityCol = new TableColumn<>("City");
        cityCol.setId("cityColumn");
        tableView.getColumns().addAll(fnCol, lnCol, cityCol);

        tableView.needsLayoutProperty().addListener((obs, old, needsLayout) -> {
            if (!needsLayout) {
                AtomicBoolean updateLayout = new AtomicBoolean();
                tableView.lookupAll(".column-header").stream().map(node -> (Region) node).forEach(column -> {
                    if (column.getProperties().get("fontLoaded") == null) {
                        switch (column.getId()) {
                            case "firstColumn":
                                updateFont(column, "Calibri", 20);
                                updateLayout.set(true);
                                break;
                            case "lastColumn":
                                updateFont(column, "Verdana", 10);
                                updateLayout.set(true);
                                break;
                            case "newColumn":
                                updateFont(column, "Verdana", 25);
                                updateLayout.set(true);
                                break;
                        }
                        column.getProperties().put("fontLoaded", true);
                    }
                });
                if (updateLayout.get()) {
                    // A timer to execute only once in the next pulse.
                    new AnimationTimer(){
                        int count = 0;
                        @Override
                        public void handle(long now) {
                            if(count>1){
                               tableView.requestLayout();
                                stop();
                            }
                            count++;
                        }
                    }.start();
                }
            }
        });

        CheckBox showLastColumn = new CheckBox("Show LastName column");
        showLastColumn.selectedProperty().addListener((obs, old, val) -> lnCol.setVisible(val));
        Button addColumn = new Button("Add Column");
        addColumn.setOnAction(e -> {
            TableColumn<Person, String> newCol = new TableColumn<>("Column " + i++);
            newCol.setId("newColumn");
            tableView.getColumns().add(newCol);
        });
        VBox root = new VBox();
        root.setSpacing(10);
        root.setPadding(new Insets(10));
        root.getChildren().addAll(showLastColumn, addColumn, tableView);
        VBox.setVgrow(tableView, Priority.ALWAYS);

        Scene sc = new Scene(root, 500, 500);
        primaryStage.setScene(sc);
        primaryStage.setTitle("ColumnHeader Custom Font");
        primaryStage.show();

    }

    private void updateFont(Region column, String fontName, int fontSize) {
        column.lookupAll(".label").stream().map(node -> (Label) node).forEach(label -> label.setFont(new Font(fontName, fontSize)));
    }

    class Person {
        // TableView item
    }
}