如何在没有 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
}
}
我希望能够在不使用 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
}
}