There are plenty of high-quality icon fonts for scalable user interfaces, and drawing them directly as Text
into JavaFX UIs is simple. But what if you need the icon as an Image
or a disk file? That’s not hard to achieve, either, but there are some non-obvious steps and many Java APIs to navigate. So I put the whole procedure together in this tutorial.
To begin with, here are the JavaFX package imports used by the rest of the code. Any AWT packages we need are explicitly specified inline.
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.scene.image.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
First we set the desired image size and create a matching JavaFX Canvas
. I’m using a 256×256 square since that’s a standard size for icons.
final double size = 256;
final Canvas canvas = new Canvas(size, size);
final GraphicsContext gc = canvas.getGraphicsContext2D();
Now we center the desired text on the Canvas
. Note that the Font
constructor doesn’t take a pixel size, but rather a point size specifying the font’s baseline distance. This means you cannot a priori determine the correct Font
size to precisely fill our Canvas
with any given icon. The Canvas
pixel size is usually a good heuristic for the Font
point size, but then you’ll simply have to check the output and tweak as necessary, e.g. with the factor 1.3 shown here.
final Font font = new Font("Ionicons", 1.3 * size);
gc.setFont(font);
gc.setTextAlign(TextAlignment.CENTER);
gc.setTextBaseline(VPos.CENTER);
gc.setFill(Color.BLACK);
gc.fillText("\ue707", size / 2, size / 2);
This sample text is a star icon (icon-star
) from the free Ionicons font, which must already have been loaded using Font.loadFont()
. Our text is now drawn on a Canvas
but we want an Image
, so let’s take a snapshot. The SnapshotParameters
force the background to remain transparent, otherwise snapshot()
would paint it solid white.
final SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
final WritableImage snapshot = canvas.snapshot(params, null);
As a final step, we want to save the image to disk for further use. Here we have a small problem because JavaFX does not support creating image files. Fortunately, AWT does and JavaFX provides a bridge method.
final java.awt.image.BufferedImage image =
javafx.embed.swing.SwingFXUtils.fromFXImage(snapshot, null);
final java.io.File file = new java.io.File("icon.png");
try {
javax.imageio.ImageIO.write(image, "png", file);
}
catch (java.io.IOException e) {
// error processing
}
The sample code uses PNG output which is appropriate for icons and supports transparency, but ImageIO
also offers other standard formats. And so we finally have the 256×256 PNG file you see below! Naturally you can use the same procedure to save any other text, or indeed any arbitrary Node
content.
2 thoughts on “JavaFX Text Icons as Images & Files”