JavaFX自定义字体

6

实际上我已经到处寻找答案,但是没有一个答案能够帮助我,所以问题来了:

我想要给我的按钮添加自定义字体。我已经尝试编写CSS类和其他解决方案,但都没有起作用。

如果有人能帮我就太好了!

更新:

package view;
import ...
public class SceneStyle {

ImageView header = new ImageView("/view/images/header.jpg");
ImageView chatImg = new ImageView("/view/images/chat_win.jpg");

//Layout Style
//public String font1 = "Impact";
//public String font2 = "Comic Sans MS";
public static String color1 = "#00adf0"; 
public static String color2 = "#0076a3"; 

public void setLabelStyle(Label label) {
    label.setStyle("-fx-font-family: Inconsolata:700; -fx-font-size: 25");
    Scene scene = new Scene(label);
    scene.getStylesheets().add("https://fonts.googleapis.com/css?family=Inconsolata:700");
    label.setTextFill(Color.GRAY);
}

public void setLabelStyle2(Label label){
    label.setStyle("-fx-font-family: Inconsolata:700; -fx-font-size: 25");
    Scene scene = new Scene(label);
    scene.getStylesheets().add("https://fonts.googleapis.com/css?family=Inconsolata:700");
    label.setTextFill(Color.GRAY);
}

public void setLabelStyle3(Label label){
    label.setStyle("-fx-font-family: Inconsolata:700; -fx-font-size: 25");
    Scene scene = new Scene(label);
    scene.getStylesheets().add("https://fonts.googleapis.com/css?family=Inconsolata:700");
    label.setTextFill(Color.RED);
}

public void setButtonStyle(Button button){
    button.setStyle("-fx-font-family: Inconsolata:700; -fx-font-size: 30; -fx-font-style: normal");
    Scene scene = new Scene(button);
    scene.getStylesheets().add("https://fonts.googleapis.com/css?family=Inconsolata:700");
    button.setTextFill(Color.web(color2));
    button.setPrefWidth(190);
}

public void setBorderPaneStyle(BorderPane pane, VBox btnBox, HBox scoreBox){

    pane.setTop(header);
    pane.setLeft(btnBox);
    pane.setRight(chatImg);
    pane.setBottom(scoreBox);
    pane.getLeft().setStyle("-fx-background-image: url(\"/view/images/border_left.jpg\");");
    pane.getBottom().setStyle("-fx-background-image: url(\"/view/images/bottom.jpg\");");
    //pane.getCenter().setStyle("-fx-background-image: url(\"/view/images/center.jpg\");");
    //TODO: why can't I implement this?
}

public static String getFontColor1(){ return color1; }
public static String getFontColor2(){ return color2; }

感谢详细的回答,但实际上我不想编写被覆盖的启动方法。只想在我的代码中实现字体。是的,现在我正在尝试使用Google字体。 感谢回答我的问题。


每次我尝试使用@font-face时都无法正常工作。 你需要通过Font.loadFont(...)在代码中加载字体。 然后你就可以在css中使用它了。 - Marcel
您可以尝试使用这个小例子,它使用@font-face加载新的字体文件,然后应用于按钮和标签控件。 - ItachiUchiha
有一个使用CSS @font-face定义的fxexperience博客,介绍如何使用Google托管字体。 - jewelsea
你提到不想编写被覆盖的启动方法。然而,在纯 JavaFX 应用程序 中,你需要这样的方法,否则你将无法让 JavaFX 做任何事情,甚至不能 说“Hello, World” ,没有一个启动方法。 - jewelsea
你只需要为应用程序添加一次给定字体的样式表。每次添加元素(例如每个按钮和每个标签)到用户界面时,不需要再添加相同的CSS样式表。而且,你也不需要为每个元素创建一个新场景,通常只需要一个单独的场景将所有可见元素添加进去。 - jewelsea
当然,我在主类中有一个start方法。 - Viktoria
3个回答

13

这是一个在JavaFX应用程序中使用自定义字体的简单示例。此示例只是FontLoad应用程序样本的编辑版本。

输出结果

图片描述


项目结构

下图为项目结构图。

图片描述


Java类

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FontLoad extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label("JavaFX Application");
        Button button = new Button("My Button");
        VBox box = new VBox(15, label, button);
        box.setAlignment(Pos.CENTER);
        Scene scene = new Scene(box, 500, 300);
        scene.getStylesheets().add(getClass().getResource("/fontstyle.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

样式表

@font-face {
    font-family: 'Fleftex';
    src: url('fonts/Fleftex_M.ttf');
}

.label {
    -fx-font-family: 'Fleftex';
    -fx-font-size: 20;
}

.button .text {
    -fx-font-family: 'Fleftex';
}

更新 >= 8u60

从这个版本开始,“font-family”属性将被忽略,您必须使用TTF的真实名称。

例如:要使用文件Fleftex_M.ttf中包含的字体“Fleftex”,您必须使用此CSS文件:

@font-face {
src: url(“fonts/Fleftex_M.ttf”);
}

.label {
-fx-font-family: 'Fleftex';
}

10
可能有些人在这里看不出来的是,@font-face 在 CSS 文件中之所以排在第一位,并非偶然。实际上,它必须放在这个位置才能起作用,否则它就会被忽略。在经过了一小时的艰苦搜索后,我才学会了这一点,找到了为什么我的字体被忽略的原因。 - smac89
“Update >= 8u60” 的解决方案对我很有效,但要注意字体路径中不要有任何空格。我的所有Java项目都位于名为“Java Projects”的文件夹中,因此无论我做什么,都会有一个空格。我不得不创建另一个没有空格的文件夹,把我的项目放在那里,现在字体可以完美加载了。 - Austin Whitelaw

2

下面是一个小例子,展示如何加载和设置自定义字体。

package createfont;

import java.io.IOException;
import java.io.InputStream;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class CustomFontTest extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        String currentFontFile = "English Gothic, 17th c..TTF";
        InputStream fontStream = CustomFontTest.class.getResourceAsStream(currentFontFile);
        if (fontStream != null) {
            Font bgFont = Font.loadFont(fontStream, 36);
            fontStream.close();

            final Button button = new Button("Press me");
            button.setFont(bgFont);

            BorderPane root = new BorderPane();
            root.setCenter(button);

            Scene scene = new Scene(root, 500, 100);

            primaryStage.setTitle("CustomFontTest");
            primaryStage.setScene(scene);
            primaryStage.show();
        } else {
            throw new IOException("Could not create font: " + currentFontFile);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

}

实际上不理解"English Gothic, 17th c..TFF"是什么意思,因为它既不是文件路径也不是正确的文件名。 - Viktoria
4
当然不是。我的假设是,您会用自己的字体文件替换它。 - mipa

0
我尝试了这个:
    public void setLabelStyle(Label label) {
    label.setStyle("-fx-font-family: Inconsolata:700; -fx-font-size: 25");
    Scene scene = new Scene(label);
    scene.getStylesheets().add("https://fonts.googleapis.com/css?family=Inconsolata:700");
    label.setTextFill(Color.GRAY);

在每个方法中。因为我不想编写一个新的方法来覆盖上面的start方法。(实际上感谢您提供了这么详细的答案,但这不是我正在寻找的)。但是我的解决方案也不太好用...


1
您不必每次都覆盖start()。您只需在扩展Application的类中执行一次即可。样式表通常只添加一次到您的场景中。 - ItachiUchiha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接