Documentation



JavaFX: Mastering FXML

2 FXML Enhancements in JavaFX Releases 2.1 and 2.2

This chapter contains the following sections that describe the FXML enhancements made in JavaFX releases 2.1 and 2.2. Also covered are the incompatibilities with previous releases:

FXML Enhancements Made in JavaFX 2.1 and 2.2

The following FXML enhancements have been added in JavaFX 2.1 and JavaFX 2.2:

  • Support for using a leading backslash as an escape character (RT-18680)

    JavaFX 2.0 used consecutive operator characters such as $$ as escape sequences. JavaFX 2.1 adds support for escape sequences using the backslash character, such as \$. These escape sequences are more similar to Unified Expression Language (UEL), making them more familiar to developers. The JavaFX 2.0 escape sequences are deprecated as of JavaFX 2.1. See Some JavaFX 2.0 FXML Escape Sequences Are Deprecated in JavaFX 2.1 and Backslash Is Now an Escape Character.

  • An implicit variable for the controller to document the namespace

    This new feature facilitates bidirectional binding between the controller and the UI. Bidirectional binding was dropped from JavaFX 2.1, but this feature was retained.

  • Convenience constructors to the FXMLLoader class (RT-16815)

    Several new convenience constructors have been added to the FXMLLoader class. These constructors mirror the static load() methods defined in JavaFX 2.0, but make it easier to access the document's controller from the calling code.

  • Customizable controller instantiation (RT-16724, RT-17268)

    In JavaFX 2.0, the calling code did not have any control over controller creation. This prevented an application from using a dependency injection system such as Google Guice or the Spring Framework to manage controller initialization. JavaFX 2.1 adds a Callback interface to facilitate delegation of controller construction:

    public interface Callback {
        public Object getController(Class<?> type);
    }
    

    When a controller factory is provided to the FXMLLoader object, the loader will delegate controller construction to the factory. An implementation might return a null value to indicate that it does not or cannot create a controller of the given type; in this case, the default controller construction mechanism will be employed by the loader. Implementations might also "recycle" controllers such that controller instances can be shared by multiple FXML documents. However, developers must be aware of the implications of doing this: primarily, that controller field injection should not be used in this case because it will result in the controller fields containing values from only the most recently loaded document.

  • Easier style sheets to work with (RT-18299, RT-15524)

    In JavaFX 2.0, applying style sheets in FXML was not very convenient. In JavaFX 2.1, it is much simpler. Style sheets can be specified as an attribute of a root <Scene> element as follows:

    <Scene stylesheets="/com/foo/stylesheet1.css, /com/foo/stylesheet2.css">
    </Scene>
    

    Style classes on individual nodes can now be applied as follows:

    <Label styleClass="heading, firstPage" text="First Page Heading"/>
    
  • Caller-specified no-arg controller method as an event handler (RT-18229)

    In JavaFX 2.0, controller-based event handlers must adhere to the method signature defined by an event handler. They must accept a single argument of a type that extends the Event class and return void. In JavaFX 2.1, the argument restriction has been lifted, and it is now possible to write a controller event handler that takes no arguments.

  • <fx:constant> tag

    The <fx:constant> tag has been added to FXML to facilitate lookup of class constants. For example, the NEGATIVE_INFINITY constant defined by the java.lang.Double class can now be referenced as follows:

    <Double fx:constant="NEGATIVE_INFINITY"/>
    
  • Improved access to sub-controllers in FXML

    In JavaFX 2.1 and earlier, it was not easy to access subcontrollers from a root controller class. This made it difficult to use a controller to open and populate a dialog window whose contents were defined in an include statement, for example.

    JavaFX 2.2 maps nested controller instances directly to member fields in the including document's controller, making it much easier to interact with nested controllers. Consider the following FXML document and controller:

    <VBox fx:controller="com.foo.MainController"> 
    ...
        <fx:include fx:id="dialog" source="dialog.fxml"/>
    ...
    </VBox>
    
    public class MainController extends Controller { 
        @FXML private Window dialog;
        @FXML private DialogController dialogController;
    
        ...
    }
    

    When the controller's initialize() method is called, the dialog field will contain the root element loaded from the dialog.fxml file, and the dialogController object will contain the include statement's controller. The main controller can then invoke methods on the include statement's controller, to populate and show the dialog, for example.

  • Support for controller initialization via reflection

    In JavaFX 2.1 and earlier, controller classes were required to implement the Initializable interface to be notified when the contents of the associated FXML document had been completely loaded. In JavaFX 2.2, this is no longer necessary. An instance of the FXMLLoader class simply looks for the initialize() method on the controller and calls it, if available. Note that, similar to other FXML callback methods such as event handlers, this method must be annotated with the @FXML annotation if it is not public.

    It is recommended that developers use this approach for new development. The Initializable interface has not been deprecated, but might be in a future release.

  • Simplified creation of FXML-based custom controls

    In previous releases, it was fairly cumbersome to create custom controls whose internal structure was defined in FXML. JavaFX 2.2 includes some subtle but powerful enhancements that significantly simplify this process. The new setRoot() and setController() methods enable the calling code to inject document root and controller values, respectively, into the document namespace, rather than delegate creation of these objects to FXMLLoader. This enables a developer to create reusable controls that are internally implemented using markup, but (from an API perspective) appear identical to controls implemented programmatically.

    For example, the following code markup defines the structure of a simple custom control containing a TextField and a Button instance. The root container is defined as an instance of the javafx.scene.layout.VBox class:

    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    
    <fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
        <TextField fx:id="textField"/>
        <Button text="Click Me" onAction="#doSomething"/>
    </fx:root>
    

    The <fx:root> tag, which was added for JavaFX 2.2, specifies that the element's value will be obtained by calling the getRoot() method of the FXMLLoader class. Prior to calling the load()method, the calling code must specify this value by calling the setRoot() method. The calling code can also provide a value for the document's controller by calling the setController() method.

    For more information, see Creating a Custom Control with FXML.

FXML Loader Incompatibilities with Previous JavaFX Releases

The following sections contain compatibility issues that users might encounter if they load a JavaFX 2.0 FXML file with a JavaFX 2.1 FXML loader:

Some JavaFX 2.0 FXML Escape Sequences Are Deprecated in JavaFX 2.1

Table 2-1 shows the double-character escape sequences that were used in FXML in JavaFX 2.0, but are deprecated in JavaFX 2.1. Instead, use a backslash as the escape character.

Table 2-1 Deprecated and Current Escape Sequences

JavaFX 2.0 Escape Sequence JavaFX 2.1 Escape Sequence

$$

\$

%%

\%

@@

\@


If Scene Builder encounters any of these deprecated escape sequences, then the console displays a warning, but loads the FXML anyway. The next time the file is saved, Scene Builder automatically replaces the deprecated escape characters with the new syntax.

Backslash Is Now an Escape Character

In JavaFX 2.1, the backslash \ is an escape character in FXML. As a result, JavaFX 2.0 applications with FXML files that contain FXML string attributes starting with a backslash might prevent the FXML from loading, or it might cause the FXML loader to misinterpret the string.

Solution: For any FXML backslash text in a JavaFX 2.0 application, add an additional backslash to escape the character.

Example:

Remove this line of code:

<Button text="\"/>

Replace it with this line of code:

<Button text="\\"/>

Close Window

Table of Contents

JavaFX: Mastering FXML

Expand | Collapse