JavaFX and scene Builder: Create UIs with a few clicks

If you like Figma, you will definitely like Scene Builder. It is a tool for creating user interfaces in JavaFX without coding. I'll show you how to do that. Scene Builder is a standalone free open source program. It is backed by Gluon, so you can download it from the company website for your platform. Install it like any other application. Now lets integrate Scene Builder with IntelliJ Idea. Open IDE settings. Select "Languages & Frameworks", "JavaFX". Here specify the path to the Scene Builder application. I use a mac, so the path would be /Applications/SceneBuilder.app Click apply. You can now right click on the FXML file with the layout and select "Open in Scene Builder". Great.

Now Scene Builder and IDE work together as a team. Before we go any further, let's stop for a moment and discuss what FXML is, because it's a key ingredient that glues together the user interface and the application code. FXML is an XML-based markup language used for creating layouts for JavaFX applications. When you are done with creating a layout in Scene Builder, you can export it as an FXML file and add it to your project. FXML files help to separate the layout code and the application code.

Of course, you need to tie the file to the application and business logic. But don't worry, we will learn how to do that in just a couple of minutes. Create a new JavaFX project. There are several ways of doing that. You can add JavaFX libraries or build from Maven archetype, But the simplest solution is to download Liberica JDK full that bundles LibericaFX, an instance of OpenJFX. Specify it as a runtime for your project and you won't need any additional dependencies. Everything will work out of the box! Okay, so this is a barebone Java project. Leave it be for a while. We'll deal with an interface first. Let's open Scene Builder and see what's what. Scene Builder has a drag-and-drop interface.

If you use Figma, you are familiar with the concept. In the top-left corner we have a Library with different graphic elements: containers, controls, etc.. In the bottom-left corner there is a Document section. It shows the hierarchy of elements you add to the layout. There's also the Controller field where you can specify the name of the Controller class in your application. On the right we have Inspector where you can customize each element. You can set the size, alignment, CSS styles, and whatnot. You can also set the properties that will tie the element to the code, and we'll see how it works in a minute. Okay. To the task at hand! We will build a small To Do app. You enter the task, click Save, and it is added to the list. Select VBox from Containers and drag it to the center of the screen. This will be our Scene. You can adjust the layout, for instance, add a background color. Go to Properties, Style, and add fx-background-color and the color that you need. Now select a TextField. Drag it to the VBox. Now Button, drag it too, and now ListView. The whole thing looks like a sidt from the 80s right now. But don't worry, we'll fix that. As you can see in the hierarchy, our nodes formed a stack. You can switch between them to adjust the settings.

For instance, let's add margins to TextField and ListView so that the button doesn't stick to them. Give a meaningful name to the button like "Save task". You can customize the elements right here in the Scene Builder. You can also attach a CSS sheet, or you can use AtlantaFX to integrate styles at ease. So, there are plenty of options. Okay, so we can add some quick touches right now. Like, for instance, change the text color or background color. Look, the button already looks better! All right. Now let's do the same to other elements. So select ListView. Let's set up the padding. And now select TextField. Let's also adjust the padding and border color. All right. The next step is pretty important. We need to add hooks for the code. The code will identify the elements in the FXML file by these hooks. So let's add id to elements. Let's also specify the method for onAction in the button. This will trigger our method for saving the task. And finally let's specify the Controller class. So we haven't created the Controller yet, but let's just specify its name here. And don't forget to create the Controller with this exact name in the application. Great. So we beautified our interface a little bit.

Of course, you can linger in the Scene Builder and experiment with other settings to create a perfect layout. But we are going further. And now it's time to connect the interface to the application code. Save the file to the resources directory of your project. Let's deal with the main application class first. It needs to extend the application from JavaFX application package. Implement the required method start. Also, call method launch from public static void main. It is necessary for when you package your application, JVM needs to find the main class. In the start method, create an instance of FXMLLoader. Set the location of the FXML class.

Now create an instance of our container VBox by loading it from the file. So, Vbox loader.load. Create a scene scene = new Scene at our box as an argument and finally set the scene on the stage. The last thing to do is to show the stage with the show method. Awesome. Right. So if you open our FXML file, you will see that the JVM is not happy. This is because we specified classes and methods that we didn't define yet in the application. That's very useful and it helps to avoid hidden bugs. Right. Well, first let's create a TaskController class. It implements Initializable interface. Implement the required method initialize. Now create the necessary fields. TextField text, Button saveButton, taskList ListView and annotate them with FXML. This way Java will understand that these are the elements from the file. Create method saveTask, annotate it with FXML too.

Now we need to extract the text from the text field and add it to the list of tasks. We can do that by calling the getItems method of ListView, and then adding the task. Clear the text field for user convenience. Great! Let's launch our application. It works! Of course, in the real world you will add a database connection to store the tasks permanently. But you already have the interface. However, we are not done yet.

Right now our interface is not very adaptive. So if you open full screen view, the list view field doesn't adjust its size. And plus the button is kinda passive-aggressive. When you hover the mouse, you can't tell whether it is active or not. Let's fix that. Go back to the file. Open it in Scene Builder If you closed it. Now, select ListView, Layout, and select Vgrow ALWAYS. Save the changes. Let's run the app again. Excellent! Now our interface is adaptive. As for the button, I mentioned that you can add a CSS sheet or use third-party tools. But let's keep it simple right now and add the animation programmatically. So we need two strings: for IDLE_BUTTON (and let's specify the color).

And the second string is going to be for HOVER_BUTTON. And let's specify another color. And now in the initialize method we can use our button and its method setOnMouseEntered. Here we will set the style HOVER_BUTTON, and next we will use its method setOnMouseExited and we set different style IDLE_BUTTON. Run the app again. Cool! Now the button is fancy.

In this video, we learned how to use Scene Builder to create user interfaces for JavaFX applications. We also learned how to connect the FXML file to the application code. As homework, you can add the delete button and add the code for deleting the task from the list. If you want to boost your Java FX skills, write in the comments which topics I should cover in my next videos. Don't forget to like, subscribe, and until next time!

Summary

In this tutorial, we use Scene Builder to visually design a JavaFX user interface without writing layout code manually. We integrate Scene Builder with IntelliJ IDEA, create a simple To-Do app, and connect UI elements from the FXML file to the Java code using a Controller class. We also improve the app’s appearance and behavior with basic styling and mouse animations, making the interface more adaptive and interactive.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Videos
card image
Jan 20, 2026
JDBC vs ORM vs jOOQ: Choose the Right Java Database Tool

Still unsure what is the difference between JPA, Hibernate, JDBC, or jOOQ and when to use which? This video clarifies the entire Java database access stack with real, production-oriented examples. We start at the foundation, which is JDBC, a low-level API every other tool eventually relies on for database communication. Then, we go through the ORM concept, JPA as a specification of ORM, Hibernate as the implementation and extension of JPA, and Blaze Persistence as a powerful upgrade to JPA Criteria API. From there, we take a different path with jOOQ: a database-first, SQL-centric approach that provides type-safe queries and catches many SQL errors at compile time instead of runtime. You’ll see when raw JDBC makes sense for small, focused services, when Hibernate fits CRUD-heavy domains, and when jOOQ excels at complex reporting and analytics. We discuss real performance pitfalls such as N+1 queries and lazy loading, and show practical combination strategies like “JPA for CRUD, jOOQ for reports.” The goal is to equip you with clarity so that you can make informed architectural decisions based on domain complexity, query patterns, and long-term maintainability.

Videos
card image
Jan 13, 2026
Hibernate: Ditch or Double Down? When ORM Isn't Enough

Every Java team debates Hibernate at some point: productivity champion or performance liability? Both are right. This video shows you when to rely on Hibernate's ORM magic and when to drop down to SQL. We walk through production scenarios: domain models with many-to-many relations where Hibernate excels, analytical reports with window functions where JDBC dominates, and hybrid architectures that use both in the same Spring Boot codebase. You'll see real code examples: the N+1 query trap that kills performance, complex window functions and anti-joins that Hibernate can't handle, equals/hashCode pitfalls with lazy loading, and practical two-level caching strategies. We also explore how Hibernate works under the hood—translating HQL to database-specific SQL dialects, managing sessions and transactions through JDBC, implementing JPA specifications. The strategic insight: modern applications need both ORM convenience for transactional business logic and SQL precision for data-intensive analytics. Use Hibernate for CRUD and relationship management. Use SQL where ORM abstractions leak or performance demands direct control.

Further watching

Videos
card image
Feb 6, 2026
Backend Developer Roadmap 2026: What You Need to Know

Backend complexity keeps growing, and frameworks can't keep up. In 2026, knowing React or Django isn't enough. You need fundamentals that hold up when systems break, traffic spikes, or your architecture gets rewritten for the third time.I've been building production systems for 15 years. This roadmap covers three areas that separate people who know frameworks from people who can actually architect backend systems: data, architecture, and infrastructure. This is about how to think, not what tools to install.

Videos
card image
Jan 29, 2026
JDBC Connection Pools in Microservices. Why They Break Down (and What to Do Instead)

In this livestream, Catherine is joined by Rogerio Robetti, the founder of Open J Proxy, to discuss why traditional JDBC connection pools break down when teams migrate to microservices, and what is a more efficient and reliable approach to organizing database access with microservice architecture.

Videos
card image
Jan 27, 2026
Sizing JDBC Connection Pools for Real Production Load

Many production outages start with connection pool exhaustion. Your app waits seconds for connections while queries take milliseconds; yet, most teams run default settings that collapse under load. This video shows how to configure connection pools that survive real production traffic: sizing based on database limits and thread counts, setting timeouts that prevent cascading failures, and implementing an open source database proxy Open J Proxy for centralized connection management with virtual connection handles, client-side load balancing, and slow query segregation. For senior Java developers, DevOps engineers, and architects who need database performance that holds under pressure.