javafxunicodescenebuilder

How to use Unicode characters with JavaFX directly from Scenebuilder


I develop applications using JavaFX and Scenebuilder to create the user interface. I am in the need of using Unicode characters on the GUI but I am not able to add them directly from Scenebuilder, which wold be more convenient. Indeed Unicode characters can be inserted programmatically quite easily

myLabel.setText("\u03B1")

but, since the strings are totally static, I would like to add the text in Scenebuilder and avoid injecting the label object in the java code and have to deal with it only to change the text.

Inserting the Unicode string directly in the FXML file did not work

<Label fx:id="myLabel" text="\u03B1"/>

The only relevant post I found is Using Unicode characters with JavaFX but it does not solve my problem.

Is there a way to add an Unicode character directly in Scenebuilder or shall I give up on this?


Solution

  • Using Unicode in FXML

    As noted in the comments, and the related question:

    Options for this are:

    1. Edit the FXML manually (outside of SceneBuilder) and write the text using XML character references:

      <Label fx:id="myLabel" text="&#x03B1;"/>
      

    OR

    1. Put "α" character as the text instead of using an escape sequence.

      <Label fx:id="myLabel" text="α"/>
      
      • In-line editing for such text in SceneBuilder is pretty limited. You can use limited dead key support in JavaFX to add some encoded characters, but it is pretty unwieldy
      • It is probably easiest to enter such characters in another editor, copy the created text and paste it into scene builder (or the FXML file that SceneBuilder is working with).

    OR

    1. Use the method documented in this answer to internationalize the text via an external property file containing Unicode characters. The text in the property file can either use the Unicode characters directly or use a \u unicode code sequence.

    OR

    1. Use a glyph library such as Ikonli if appropriate (e.g. for emojis and other common icons). Such libraries can be used from SceneBuilder but how to do so is outside of the scope of this answer.

    Using Internationalization Features to display Unicode Characters in Scene Builder

    This can be accomplished using a resource file as documented in the Oracle Scene Builder User Guide: Internationalizing Your FXML Layout.

    Even though the Internationalization feature is targeted at internationalizing applications, it can also be used to help display Unicode characters that would otherwise be hard to type directly into SceneBuilder.

    1. Internationalize the text in SceneBuilder

    Select the node containing the text to customize and choose "Replace with Internationalized String".

    replace text

    Enter the resource key that you wish to use, for this example, I used the text "alpha".

    alpha

    2. Save the FXML

    For the saved FXML1, SceneBuilder will create a file like this where the resource key is encoded as %alpha. The % character indicates that it is a resource key.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.StackPane?>
    <?import javafx.scene.text.Font?>
    
    <StackPane prefHeight="50.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1">
       <children>
          <Label text="%alpha">
             <font>
                <Font size="26.0" />
             </font></Label>
       </children>
    </StackPane>
    

    3. Create a properties file containing the internationalized string

    src/main/resources/org/example/resourcefx/resources.properties

    alpha=\u03B1
    

    If you need other languages and locales you can add additional files for them. However, if you don't, then just the default file with no _en_US (or other) language and locale suffix suffices.

    4. Test the resource via preview

    SceneBuilder will now display the Unicode text.

    preview

    5. Use the FXML and resource in an Application

    display

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    import java.io.IOException;
    import java.util.ResourceBundle;
    
    public class ResourceApplication extends Application {
        @Override
        public void start(Stage stage) throws IOException {
            FXMLLoader fxmlLoader = new FXMLLoader(
                    ResourceApplication.class.getResource(
                           "resource-view.fxml"
                    )
            );
            fxmlLoader.setResources(
                    ResourceBundle.getBundle(
                            "org.example.resourcefx.resources"
                    )
            );
    
            stage.setScene(new Scene(fxmlLoader.load()));
            stage.show();
        }
    
        public static void main(String[] args) {
            launch();
        }
    }
    

    Where to put the files

    Following the Maven standard directory layout:

    .
    ├── pom.xml
    └── src
        └── main
            ├── java
            │   ├── module-info.java
            │   └── org
            │       └── example
            │           └── resourcefx
            │               └── ResourceApplication.java
            └── resources
                └── org
                    └── example
                        └── resourcefx
                            ├── resource-view.fxml
                            └── resources.properties
    

    You can place resources.properties in any package you want (or use the unnamed package). Here I have used the same package for the resources that I used for the application. Doing so may also help avoid any potential resource resolution issues in modular applications.


    1. Normally I would use external CSS to set the font, rather than directly setting the font in FXML via SceneBuilder. I just set the font in FXML like this for easy demonstration purposes.