This project offers a builder pattern API for JavaFX UI components, facilitating the creation of JavaFX applications through a fluent, strongly typed, and declarative approach.
The UI code that uses the builder API can represent nested structures that reflect the container hierarchy of the UI.
The builder API is generated by a code generator included in this project. This generator analyzes the JavaFX API using reflection and automatically produces builder classes.
// Example using the builder API
StringProperty textProp = new SimpleStringProperty("100");
StageBuilder
.withScene(
SceneBuilder
.withRoot(
HBoxBuilder
.withChildren(
TextFieldBuilder.create()
.textPropertyApply(prop -> prop.bindBidirectional(textProp))
.style("""
-fx-font-weight: bold;
-fx-alignment: center;
""")
.hGrowInHBox(Priority.ALWAYS)
.maxWidth(Double.MAX_VALUE)
.build(),
ButtonBuilder.create()
.text("Send")
.onAction(e -> System.out.println("Sending..."))
.minWidth(50)
.build()
)
.padding(new Insets(10))
.build()
)
.width(150)
.height(100)
.build()
)
.build()
.show();This project aims to reintroduce builder classes to JavaFX.
The builder classes were included in JavaFX 2 but were removed from the official class library due to concerns about maintenance overhead and memory usage, as noted in a 2013 post:
https://mail.openjdk.org/pipermail/openjfx-dev/2013-March/006725.html
The three advantages of the builder classes mentioned in that post remain valid today:
- Ability to set up generic configurations once and "stamp out" multiple copies.
- Structured code style that closely approximates the "container hierarchy" of the UI.
- Strongly-typed "declarative" style programming.
These advantages are especially appealing for JavaFX users working with Java (rather than Scala or Kotlin), as they enable a declarative and hierarchical coding style typical of other frameworks.
Concerns about memory usage have likely decreased compared to a decade ago. Even if they are not included in the official JavaFX API, it is beneficial for third parties to offer builder classes as an option.
My approach utilizes reflection to automatically generate the builder classes, while certain aspects that cannot be automated are handled through a few mapping rules. Unlike JavaFX 2.0, the builder classes do not have inheritance relationships, which may increase memory consumption. Additionally, builders may incur call overhead. Nonetheless, the builder classes appeal to those who prefer this programming style.
- Keep the basic API simple, with minimal new concepts to learn. Fundamentally, this is a wrapper that incorporates the builder pattern into the original JavaFX API.
- Add flavors that fluent API enthusiasts will enjoy on top of the original JavaFX API.
API Overview:
JavaDoc pages:
https://sosuisen.github.io/javafx-builder-api/
Generated Source Code:
The generated JavaFX Builder API source code is available at: https://github.com/sosuisen/javafx-builder-api/tree/main/api/
Most of the code comprises simple wrapper classes generated through mechanical transformation rules outlined in ./docs/API.md.
io.github.sosuisen
Add builder components corresponding to the JavaFX components specified in your dependencies.
e.g.) The builder class component corresponding to javafx-controls is javafx-builder-controls.
Specify a builder with the same major version as the JavaFX major version.
Example: The builder API corresponding to javafx-controls 25.0.2 is javafx-builder-controls 25.y.z.
Note: The builder API does not adhere to semantic versioning. To clarify compatibility, the major version always matches the corresponding JavaFX version. Thus, minor versions may include not only API additions but also breaking changes, although I strive to minimize these. Patch versions consist of bug fixes with no API changes.
In the example below, please specify a version for ${javafx.builder.version}.
| type | name |
|---|---|
| JPMS module | io.github.sosuisen.api.jfxbuilder.controls |
| package | io.github.sosuisen.jfxbuilder.controls |
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-controls</artifactId>
<version>${javafx.builder.version}</version>
</dependency>| type | name |
|---|---|
| JPMS module | io.github.sosuisen.api.jfxbuilder.graphics |
| package | io.github.sosuisen.jfxbuilder.graphics |
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-graphics</artifactId>
<version>${javafx.builder.version}</version>
</dependency> | type | name |
|---|---|
| JPMS module | io.github.sosuisen.api.jfxbuilder.media |
| package | io.github.sosuisen.jfxbuilder.media |
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-media</artifactId>
<version>${javafx.builder.version}</version>
</dependency> | type | name |
|---|---|
| JPMS module | io.github.sosuisen.api.jfxbuilder.web |
| package | io.github.sosuisen.jfxbuilder.web |
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-web</artifactId>
<version>${javafx.builder.version}</version>
</dependency> <properties>
<javafx.version>25.0.2</javafx.version>
<javafx.builder.version>25.0.0</javafx.builder.version>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-controls</artifactId>
<version>${javafx.builder.version}</version>
</dependency>
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-graphics</artifactId>
<version>${javafx.builder.version}</version>
</dependency>
</dependencies>The builder implementation depends solely on the original JavaFX compoment.
Important: Maven automatically manages transitive dependencies for JavaFX components; however, builder API components must be installed individually.
For example, javafx-builder-graphics is generally required when your project depends on javafx-controls, since javafx-graphics is a transitive dependency.
pom.xml
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-controls</artifactId>
<version>${javafx.builder.version}</version>
</dependency>
<dependency>
<groupId>io.github.sosuisen</groupId>
<artifactId>javafx-builder-graphics</artifactId>
<version>${javafx.builder.version}</version>
</dependency>
</dependencies>module-info.java
module com.example.app {
requires javafx.controls;
requires io.github.sosuisen.api.jfxbuilder.controls;
requires io.github.sosuisen.api.jfxbuilder.graphics;
opens com.example to javafx.graphics;
}For comfortable use of the JavaFX Builder API, maintain matching indentation of opening and closing parentheses.
I have prepared an Eclipse code formatter profile (XML) for the JavaFX Builder API.
You can import it into your IDE or place it in your project folder.
Download it here: Customized GoogleStyle for JavaFX builder
The BMI (Body Mass Index) calculator demonstrates modern JavaFX development utilizing MVVM architecture, fluent UI construction, and internationalization support.
https://github.com/sosuisen/bmi-mvvm-with-builder
You can also generate and install the API in your local repository for your use.
To generate it yourself, please refer to the instructions in Generate builder classes.
MIT
