2013-01-15

Using custom fonts in your JavaFX application

If you want to use custom fonts in your JavaFX application you basically have two options. You can perform the loading of the fonts yourself and assign them to your components programmatically:

final Font myFancyFont =
    Font.loadFont(getClass().getResourceAsStream("/My Fancy Font.ttf"), 12.0);

Label label = LabelBuilder.create().setText("w00t w00t!").build();

// First way to set the font:
// Just pass the reference to the object that we created
// a few lines above.
label.setFont(myFancyFont);

// Second way:
// Use a FontBuilder to fetch the font. The name of the font must match
// the name that is embedded into the font's information / metadata!
label.setFont(FontBuilder.create().name("My Fancy Font").build());

There is an easier way to achieve your goal, though: Add a file called "fonts.mf" (basically some kind of "Java Properties" file) into your application's META-INF folder with the following contents:

My\ Fancy\ Font\ Alias = /My\ Fancy\ Font.ttf

(Make sure to escape all whitespaces!)

That way, JavaFX will make sure that your font will be loaded automatically upon application initialization, so you don't have to worry about custom loading routines, font-reference-handling and so on and so on. You can now reference your font using it's alias ("My fancy Font Alias") or the name that was provided in the meta information of the true type font.

UPDATE (June 2013)
Looks like the font loading mechanism via META-INF/fonts.mf is broken or has been abandoned in JavaFX 8. To work around these issues I suggest you still use META-INF/fonts.mf for your apps, but add the following snippet of code into your application's init method, to work around these issues:
 try {
    final Enumeration fontDefinitions = getClass().getClassLoader().getResources("META-INF/fonts.mf");
    while (fontDefinitions.hasMoreElements()) {
        final Properties props = new Properties();
        props.load(fontDefinitions.nextElement().openStream());
        for (final Object v: props.values()) {
            final String fontName = (String) v;
            Font.loadFont(getClass().getResourceAsStream(fontName), 10.0);
        }
    }
} catch (final IOException e) {
    throw new IllegalStateException("Unable to load custom fonts from META-INF/fonts.mf file(s).", e);
}


2 comments:

  1. Hi,

    I get the following errors

    error: cannot find symbol
    props.load(fontDefinitions.nextElement().openStream());
    symbol: method openStream()
    location: class Object
    /Users/ossama/NetBeansProjects/PrayerTime/src/javafxapplication4/JavaFXApplication4.java:130: error: cannot find symbol
    Font.loadFont(getClass().getResourceAsStream(fontName), 10.0);
    symbol: method loadFont(InputStream,double)
    location: class Font
    2 errors
    1 warning

    Plese help

    ReplyDelete
  2. Hi,

    works fine for me. I like to have complete control over the look and feel of my applications, especially over fonts as they tend to turn out differently on every system.
    I translated your example to Scala code for use with ScalaFX:

    https://gist.github.com/aerben/8fe7b4475a57eca1ec01

    Kind regards
    Alex

    ReplyDelete