I want to create a custom control in an executable jar file and then use in Gluon Scene Builder 11.00. I need to know how to do this. I tried several forms but my controls not appear when import jar in Scene Builder. I am using IntelliJ Community Edition 2019.2 and Gluon Scene Builder 11.00 and Java 12.0.2. Anyone please that could help me with a little example?
Maven Project.
custom_control.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="138.0" type="VBox" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="textField" />
<Button mnemonicParsing="false" onAction="#doSomething" prefHeight="25.0" prefWidth="142.0" text="Clck Me" />
</children>
</fx:root>
CustomControl.java
package customcontrolexample;
import java.io.IOException;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
public class CustomControl extends VBox {
@FXML private TextField textField;
public CustomControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"custom_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public String getText() {
return textProperty().get();
}
public void setText(String value) {
textProperty().set(value);
}
public StringProperty textProperty() {
return textField.textProperty();
}
@FXML
protected void doSomething() {
System.out.println("The button was clicked!");
}
}
CustomControlExample.java
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class CustomControlExample extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
CustomControl customControl = new CustomControl();
customControl.setText("Hello!");
stage.setScene(new Scene(customControl));
stage.setTitle("Custom Control");
stage.setWidth(300);
stage.setHeight(200);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>customcontrol</groupId>
<artifactId>CustomControlExample</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>12.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>12.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>CustomControlExample</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>CustomControlExample</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Create class file with extending combo box, controller and add controller in FXML file (in scene builder). Find "Import from JAR/FXML file" in combo box near to left search box in scene builder and then select the file. Now you have new title pane in left accordion with name Custom. There you can find your components.
Scene Builder is open source, and it is freely licensed under the BSD license. Gluon can provide custom consultancy, training, and open source commercial support.
There are a few things to consider when you want to create a custom control that can be imported with Scene Builder.
What qualifies as custom control
There is no documentation about this, but you can have a look at the current source code in Scene Builder that explores all the classes in a jar, and finds valid classes as custom controls:
java.
, javax.
, javafx.
,
com.oracle.javafx.scenebuilder.
, com.javafx.
, com.gluonhq
.Node
. This is quite important: the class should be a subclass of a JavaFX node, like a container (i.e. extends from VBox
) or a built-in node (i.e. extends from Button
).For all the classes found, then an FXML is built with something like:
<?import your.class.fullname?>
<your.class.simplename />
If that FXML can be loaded by the FXMLLoader
, then it is a custom control.
Otherwise it is discarded.
Type of custom control
There are several approaches on how to build a custom control, but if you are going to use FXML this old tutorial gives some important clarification on how to use fx:root
and how to define the controller, like:
public class CustomControl extends VBox {
public CustomControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"custom_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
...
}
Java 11 level
Finally, since Scene Builder 11 runs on Java 11, the jar has to be compiled with support for Java 11.
Using Maven:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
Before going to Scene Builder, you can try your custom control in a demo project. This will help you find and solve possible issues in advance.
Scene Builder 11
Once you have built the control, you can open Scene Builder 11 and import it following the documentation.
Basically, using the option Add Library/FXML from file system
and browsing your file system to locate the jar.
Note: there is a merged PR that will allow using the build/target directory of a project, instead of requiring a jar.
In case of the posted custom control, you should get this:
If the view doesn't show your control, there is an issue that you have to solve first.
Note: there is a pending PR that will provide more information when the process fail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With