如何在JavaFx 2.2中嵌入.ttf字体?

28
首先,我对编码还比较陌生。我需要在我的Java FXML应用程序中嵌入一个字体,但不知道如何操作。我已将字体fontName.ttf粘贴到项目源文件的“资源”文件夹中,即App/src/app/resources。我已将组件(文本)的CSS设置为:
#text {
    -fx-font-family: url(resources/fontName.ttf);
}

我还尝试在URL中添加引号,例如: url("resources/fontName.ttf");,但它不起作用。我还为组件设置了CSS ID,因此那不可能是问题的原因。是否有其他有效的方法来嵌入字体?我看过http://fxexperience.com/2010/05/how-to-embed-fonts/,但它不适用于我使用的JDK 1.7 u21版本。有没有正确的方法来嵌入字体?

2个回答

47

解决方案

我更新了来自Javafx How to display custom font in webview?的示例,以演示在JavaFX控件中使用自定义TrueType字体并应用CSS样式。

关键点如下:

  1. 将字体文件放置在应用程序类的相同位置,并确保您的构建系统将其放入二进制构建包(例如应用程序jar文件)中。
  2. 在应用样式之前,在JavaFX代码中加载所需的字体代码。Font.loadFont(CustomFontApp.class.getResource("TRON.TTF").toExternalForm(), 10);
  3. 要在样式类中使用自定义字体,请使用-fx-font-family CSS属性,并仅引用字体名称(例如,在此示例中为"TRON")。
  4. 创建并加载定义样式类的样式表。
  5. 将样式类应用于您的控件。

附加信息

如果您正在使用Java 8,则可能会对在JavaFX中使用Web(Google)字体感兴趣。

字体集合

如果您的字体文件以.ttc格式存在,其中包含单个文件中的多个字体,则使用Font.loadFonts API(而不是Font.loadFont)。请注意,Font.loadFonts仅适用于JDK 9及更高版本,而在之前的版本中不可用。

使用自定义字体的示例输出

tronfonts

示例代码

该示例依赖于可以从dafont下载的TRON.TTF字体。

CustomFontApp.java

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

// demonstrates the use of a custom font.
public class CustomFontApp extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) {
    stage.setTitle("TRON Synopsis");

    // load the tron font.
    Font.loadFont(
      CustomFontApp.class.getResource("TRON.TTF").toExternalForm(), 
      10
    );

    Label title = new Label("TRON");
    title.getStyleClass().add("title");

    Label caption = new Label("A sci-fi flick set in an alternate reality.");
    caption.getStyleClass().add("caption");
    caption.setMaxWidth(220);
    caption.setWrapText(true);
    caption.setTextAlignment(TextAlignment.CENTER);

    VBox layout = new VBox(10);
    layout.setStyle("-fx-padding: 20px; -fx-background-color: silver");
    layout.setAlignment(Pos.CENTER);
    layout.getChildren().setAll(
      title,
      new ImageView(
        new Image(
          "http://ia.media-imdb.com/images/M/MV5BMTY5NjM2MjAwOV5BMl5BanBnXkFtZTYwMTgyMzA5.V1.SY317.jpg"
        )
      ),
      caption
    );

    // layout the scene.
    final Scene scene = new Scene(layout);
    scene.getStylesheets().add(getClass().getResource("custom-font-styles.css").toExternalForm());
    stage.setScene(scene);
    stage.show();
  }
}

自定义字体样式.css

/** file: custom-font-styles.css
 * Place in same directory as CustomFontApp.java 
 */

.title {
    -fx-font-family: "TRON";
    -fx-font-size: 20;
}

.caption {
    -fx-font-family: "TRON";
    -fx-font-size: 10;
}

关于FXML的使用

Font.loadFont(url, size)是一个带有两个参数的静态方法。我认为你不能从FXML中调用font.loadFont,如果可以的话也不建议这样做。相反,在加载需要该字体的FXML或样式表之前,在Java代码中加载字体(如我的答案中所示)。


错误出现并显示找不到符号: loadFont 在类 Font 中。 需要三个标识符。(我在FXML中导入字体为 import javafx.scene.text.Font;) - Pratik Anand
1
在答案中添加了关于FXML使用的部分。 - jewelsea
出现错误。请在此处查看:https://docs.google.com/document/d/1GSQeo8CHQhMEU_nS-gl6yWL1qQF4T08kYwPa_OELer4/edit?usp=sharing - Pratik Anand
猜想错误可能出在其他代码逻辑上。如果浪费了您的时间,很抱歉,但还是感谢您提供答案。 - Pratik Anand
我已经尝试了几个在Windows中正常工作的版本。然而,我无法使其在Linux(Raspbian)上工作。对我有效的是: String fontPath = "/tron/TRON.TTF"; String fontURL = getClass().getResource( fontPath ).toExternalForm(); System.out.println("Font to be loaded: " + fontURL); Font.loadFont( fontURL, 10); - SergioMP
显示剩余4条评论

21

我知道你并没有要求提供一个使用自定义TTF字体在JavaFX应用程序中的纯编程方式,但我想也许对某些人来说看到一个编程版本会有所帮助:

public class Test2 extends Application {

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

  public void start(final Stage primaryStage) {
    Group rootGroup = new Group();

    // create a label to show some text
    Label label = new Label("Demo Text");
    try { 
      // load a custom font from a specific location (change path!)
      // 12 is the size to use
      final Font f = Font.loadFont(new FileInputStream(new File("./myFonts/TRON.TTF")), 12);
      label.setFont(f); // use this font with our label
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }

    rootGroup.getChildren().add(label); 

    // create scene, add root group and show stage
    Scene scene = new Scene(rootGroup, 640, 480, Color.WHITE);
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

对我来说,这个方法很有效。您可以将字体放在任何位置,只需确保适应路径即可。

您可以在此处找到有关在JavaFX应用程序中使用字体的更多信息。(链接)

希望能对您有所帮助!


在撰写本文时,已经快到2022年了(2021年12月14日),我发现一些用于在JavaFX中加载字体的方法似乎不再起作用。这个方法对我有用,所以感谢@Chris(+1赞)。嘿,我是马里奥! - JΛYDΞV

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