FXML Markup Inheritance in JavaFX

JavaFX makes it possible to define components either by code or in FXML. Typically, one would like to be able to extend components created in this way. This short tutorial shows how to extend components defined with FXML. For the other case, please refer to the code in e.x. javafx.scene.layout.Pane.

A basic, extensible component, has to define a node where a derived component can be added to. A very simple example for such an component:

BasicButton.fxml

<fx:root type="javafx.scene.layout.HBox" 
	xmlns:fx="http://javafx.com/fxml/1"
	alignment="CENTER_LEFT">
	<children>
		<Button text="Button" onAction="#changeLabel" />
		<Label fx:id="label" text="Basic Button" />
		<HBox fx:id="extension" alignment="CENTER_LEFT"/>
	</children>
</fx:root>

BasicButton.java

@DefaultProperty("extension")
public class BasicButton extends HBox {
	
	private @FXML Label label;
	private @FXML HBox extension;
	
	public BasicButton() {
		// load BasicButton.fxml
	}
	public ObservableList<Node> getExtension() {
   	return extension.getChildren();
	}
	// ... more component related code
}

The most important part here is the HBox fx:id="extension" which will serve as an extension point in the BasicButton component.

In the BasicButton java class, the extension point has to be introduced with the @DefaultProperty("extension") annotation (fx:id extension corresponds with the value for the annotation) and also the getter for the property has to be defined (ObservableList<Node> getExtension()).

Now the BasicButton can be extended in a regular java manner:

SpecializedButton.fxml

<fx:root type="mrak.jfx.extendfxml.BasicButton"
	xmlns="http://javafx.com/javafx/8" 
	xmlns:fx="http://javafx.com/fxml/1">
	<Label fx:id="anotherLabel" text="Specialized Button"/>
</fx:root>

and

SpecializedButton.java

public class SpecializedButton extends BasicButton {
	public SpecializedButton() {
		// load SpecializedButton.fxml
	}
	// … more component related code
}

Resources

Complete project with sample code on github