Search code examples
javajavafxfxml

Reusable constants for FXML layouts?


This is somewhat a follow up to my previous question. Somehow, I got the solution for my question from here, but it never really answered my question for some reasons, which led me to ask this question.

Here's the reason why:

  • I found out that by using the FXMLLoader.namespace, the mapped values are only accessible for the layout (FXML file) which the FXMLLoader is being loaded. This doesn't met the desire of having reusable constants for other FXML files though.
  • Additionally, since these constants are defined in a Java code, it is considered an error by the IDE when used because they are not directly defined within the FXML file, which then becomes hard to track down other exceptional errors.

So the question now is, how to make constants reusable for FXML layouts?

Like in Android, a Color resource for example:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="white">#FFFFFF</color>
</resources>

Can be applied to an XML layout's attribute:

android:textColor="@color/white"

Is there any other possible way in JavaFX? Thanks for all answer.


Solution

  • So I came up with a solution and thought of answering my own question. This is not the best, but I hope it'll be useful in the future.

    This is pretty simple, we can define a getter method for each constant fields, in this case, we can easily access their value from FXML using Expression Binding. Here's an example:

    Theme.class

    package styles;
    
    import javafx.scene.paint.Color;
    
    public final class Theme {
    
      /** Constant field; use Theme.BASE_COLOR */
      public static final Color BASE_COLOR = Color.TEAL;
    
      /** Getter method for FXML; use ${theme.baseColor} */
      public Color getBaseColor() { return BASE_COLOR; }
    }
    

    layout.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.text.Text?>
    
    <HBox xmlns="http://javafx.com/javafx"
          xmlns:fx="http://javafx.com/fxml"
          alignment="CENTER">
    
      <fx:define>
        <!--
            Define a reference to our Theme class.
            This is convenient because we only need a single
            instance of our Theme class for every FXML file.
        -->
        <styles.Theme fx:id="theme"/>
      </fx:define>
    
      <children>
        <!-- Now, we can simply use an expression binding here -->
        <Text text="Hello, World!" fill="${theme.baseColor}"/>
      </children>
    
    </HBox>