Compiled expressions
FXML/2 supports compiled expressions for one-time evaluation, observation, and bindings. These expressions are implemented as intrinsic markup extensions and compiled to specialized code by the FXML compiler.
| Markup extension | Prefix notation | Usage |
|---|---|---|
fx:Evaluate | $source | value supplier, property consumer |
fx:Observe | ${source} | value supplier, property consumer |
fx:Push | >{source} | property consumer |
fx:Synchronize | #{source} | property consumer |
{fx:Evaluate} has the lowest runtime overhead, since no listener maintenance is required after the initial assignment. {fx:Observe}, {fx:Push}, and {fx:Synchronize} may require listeners or additional generated code to update the target and/or the source.
Setting up a binding
Here’s how a simple binding is specified in FXML, using different but equivalent notations:
<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://jfxcore.org/fxml/2.0"
fx:subclass="com.sample.MyControl">
<!-- fx:Observe markup extension with source path -->
<Button text="{fx:Observe source=caption}"/>
<!-- 'source' is the default property of the fx:Observe markup extension, so it can be omitted -->
<Button text="{fx:Observe caption}"/>
<!-- Prefix notation, similar to classic FXML -->
<Button text="${caption}"/>
</VBox>
public class MyControl extends MyControlBase {
private final StringProperty caption = new SimpleStringProperty("Click me");
public StringProperty captionProperty() {
return caption;
}
public MyControl() {
initializeComponent();
}
}
Applying expressions to properties
When an intrinsic expression is assigned to a property (so it acts as a property consumer), the following operations are performed on the target property:
| Markup extension | Prefix notation | Operation |
|---|---|---|
{fx:Evaluate source} | $source | assign the resolved value once |
{fx:Observe source} | ${source} | Property.bind(source) |
{fx:Push source} | >{source} | add a target listener that pushes updates to source |
{fx:Synchronize source} | #{source} | Property.bindBidirectional(source) |
{fx:Evaluate ..source} | $..source | Collection.addAll(source)Map.putAll(source) |
{fx:Observe ..source} | ${..source} | Bindings.bindContent(target, source) |
{fx:Push ..source} | >{..source} | Bindings.bindContent(source, target) |
{fx:Synchronize ..source} | #{..source} | Bindings.bindContentBidirectional(target, source) |
Since source is the default property of all intrinsic expression extensions, {fx:Observe source=mySource} and {fx:Observe mySource} are equivalent.
This documentation will use the prefix notation in most code samples.