How to create JavaFX FXML custom component

Each developer needs to create custom components very often, but in JavaFX with FXML forms it is not so simple.
Here is a simple guide, how can you create your FXML custom component and how can you use it in your FXML form.
You can download source code at the end of the post.
[wp_ad_camp_1]

Prerequisites

Before we start, you will need:

Create FXML custom component

Create FXML file “Hello.fxml”

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>

<fx:root type="javafx.scene.layout.BorderPane" xmlns:fx="http://javafx.com/fxml">
    <bottom>
        <Label fx:id="lblHello" alignment="CENTER" contentDisplay="CENTER" prefHeight="67.0" prefWidth="510.0" text="..." />
    </bottom>
    <center>
        <Button fx:id="btnHello" mnemonicParsing="false" onAction="#btnHelloOnAction" text="Say hello" />
    </center>
</fx:root>

The FXML file contains simple BorderPane form with one button and label. Here is preview from Java FX Scene Builder

[wp_ad_camp_1]

Create Hello component java class “Hello.java”

package org.korecky.myjavafx.fxml;

import java.io.IOException;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;

/**
 *
 * @author Vladislav Korecký
 */
public class Hello extends BorderPane {

    private static final Logger logger = Logger.getLogger(Hello.class.getName());
    @FXML
    private Label lblHello;

    public Hello() {
        super();
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Hello.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    // Handler for Button[id="btnHello"] onAction
    public void btnHelloOnAction(ActionEvent event) {
        lblHello.setText("Hello");
    }
}

We have now prepared simple Hello component which displays “Hello” text in label when user clicks on button “Say Hello”

Now we can implement our component to main FXML form. Before we will continue, please build JAR file. Because I have maven project, I can do that by command “mvn clean install”. Maven will create MyJavaFX.jar in my “target” directory. Of course, you can build your project by ant too, depends only on your preferences. This JAR contains our custom component.
[wp_ad_camp_1]

Create Main FXML form with Controller

I have prepared Main.fxml file which contains only BorderPane and Pane in TOP with label “MyJavaFX”:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?> 
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>

<BorderPane id="" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="232.0" prefWidth="289.0" xmlns:fx="http://javafx.com/fxml" fx:controller="org.korecky.myjavafx.fxml.MainController">
  <stylesheets>
    <URL value="@../css/Main.css" />
  </stylesheets>
  <top>
    <Pane id="pnHeader" prefHeight="67.0" prefWidth="790.0">
      <children>
        <Label id="lblTitle" layoutX="14.0" layoutY="15.0" text="MyJavaFX">
          <textFill>
            <Color blue="0.250" green="0.250" red="0.250" fx:id="x1" />
          </textFill>
        </Label>
      </children>
    </Pane>
  </top>
</BorderPane>

Here is the form preview:

Of course, I have created Controller for “Main.fxml”, “MainController.java”:

package org.korecky.myjavafx.fxml;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javafx.fxml.Initializable;

/**
 *
 * @author Vladislav Korecký
 */
public class MainController implements Initializable {

    private static final Logger logger = Logger.getLogger(MainController.class.getName());

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }
}

[wp_ad_camp_1]

Let’s use our component in Main FXML form

At first, we have to add import оf our component class to the “Main.fxml”, then we can use our component as XML element.

<?import org.korecky.myjavafx.fxml.*?>

We can also add “scenebuilder-classpath-element”, this element helps JavaFX Scene Builder find required classes. If you don’t use Scene Builder, you can skip this step.

<?scenebuilder-classpath-element ../../../../../../../target/MyJavaFX.jar?>

We can add our “Hello” component to the BorderPane.

<center>
    <Hello />
</center>

Here is complete Main.fxml file with added custom component.

<?xml version="1.0" encoding="UTF-8"?>

<?scenebuilder-classpath-element ../../../../../../../target/MyJavaFX.jar?>
<?import org.korecky.myjavafx.fxml.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?> 
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>

<BorderPane id="" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="232.0" prefWidth="289.0" xmlns:fx="http://javafx.com/fxml" fx:controller="org.korecky.myjavafx.fxml.MainController">
  <center>
    <Hello />
  </center>
  <stylesheets>
    <URL value="@../css/Main.css" />
  </stylesheets>
  <top>
    <Pane id="pnHeader" prefHeight="67.0" prefWidth="790.0">
      <children>
        <Label id="lblTitle" layoutX="14.0" layoutY="15.0" text="MyJavaFX">
          <textFill>
            <Color blue="0.250" green="0.250" red="0.250" fx:id="x1" />
          </textFill>
        </Label>
      </children>
    </Pane>
  </top>
</BorderPane>

Finished

We are done. You can start application now, you should see window with button “Say Hello”, when you click on the button, label should display text “Hello”.
Here is complete source code (maven project):
Complete source code


[wp_ad_camp_1]

Leave a Reply

Your email address will not be published. Required fields are marked *