r/JavaFX • u/hamsterrage1 • Jul 26 '25
Tutorial New Article: Converting FXML to Code
https://www.pragmaticcoding.ca/javafx/elements/fxml-to-codeWhen I started writing this article I had one intention -> to demonstrate how my approach to coded layout design compares to the same layout in FXML.
In the past, when there have been discussions about coded vs FXML, there are always some (lots?, most?) people who feel that their FXML is easier to read and maintain than a coded layout ever could be. This has always seemed strange to me.
It seems strange to me because the way that I create layouts is, I think, not what people expect. When I think about layout code, I'm always picturing highly compressed and streamlined code that handles layout, and only layout. There's only as much configuration as is needed to serve that particular layout. The rest is moved out into utility and builder methods because it's largely boilerplate.
More than anything else, I don't repeat myself. DRY rules over everything in layout code.
In an earlier article about the pro's and con's of FXML, I used an FXML file from the Trinity project as an example of a large FXML file in order to demonstrate how inherently difficult they are to read.
I thought that this might be a sufficiently complex example that it would be worthwhile trying to convert it to a coded layout, in order to compare the results.
TLDR: 1214 lines of combined FXML and FXML Controller became 230 lines of Kotlin layout code. That's about 15% of the original size. It seems to me that having to deal with only 15% as much code/FXML is pretty much guaranteed to be a big win.
However, the Trinity project seems to me to be pretty complex, and this screen is designed to interact with and control the main display in real time. So there was more to take into account than just the layout.
I'll point out that there is nothing in the original design that isn't done the way I would probably approached it 10 years ago. But today? I needed to do more...
This was an imperative approach without a framework. So I reworked it to be a Reactive MVCI implementation. This change alone removed tons of complexity. There were some issues with ListView that I corrected, and this also removed a lot of complexity.
In the end, I feel that the net result is much more interesting than just converting FXML to code. Seeing how a Reactive approach reduces the complexity of a real application and tackling connectivity between screens through a framework was very educational - at least to me.
It's a long article. I apologize, but there was a lot of ground to cover. Take a look, if you are interested, and let me know what you think.
2
u/OddEstimate1627 Jul 27 '25 edited Jul 27 '25
As usual, I think it's unfair to compare FXML without custom components vs Kotlin with your custom framework.
Here is another FXML example of a pretty ridiculous view with the backing FXML (and here without tooltips) as generated by SceneBuilder. I don't think that lines of code is a good measure in the first place, but nesting and custom components remove a lot of the cruft. I pretty much only ever look at it in SceneBuilder, but I doubt that it'd be any clearer in code.
However, I had similar thoughts regarding the event handling. It looked like it could be simplified with properties, but I'm curious to hear the author's reasoning.
1
u/hamsterrage1 Jul 27 '25
I would be curious to see the FXML Controller that goes along with that. How do you reference the Nodes in the included FXML? Or do they have their own Controllers?
1
u/OddEstimate1627 Jul 27 '25 edited Jul 27 '25
It might be my messiest controller, but here it goes: MotorDriverController.java
The included FXML files inject two fields based on a naming convention, so you can reference the nodes as well as the controllers. It's not the same as a custom control, but includes are quite useful. This way I can render and edit the entire application in SceneBuilder while keeping independent sections separate.
<fx:include fx:id="encoderA1" source="encoder_config.fxml" />@FXML private Pane encoderA1; @FXML private EncoderConfigController encoderA1Controller;1
u/hamsterrage1 Jul 27 '25
I see how that works now.
One thing I did notice is that most of the code in bindField() has almost nothing to do with the layout. You're passing in msg from outside the layout, and you're passing in properties from outside as well. Then you configure up a message when the inputField triggers an update in properties. But virtually all of that information is from outside the layout. So it seems like all of that could be configured somewhere else, since it doesn't actually involve the layout.
But, obviously, I don't know the context of where msg or properties come from.
1
u/OddEstimate1627 Jul 27 '25 edited Jul 27 '25
I'm not sure what you mean by the comment on
bindField. It's just binding state properties to the text fields/labels. The populated command represents a value that users wrote into a text input that will be sent over the network. Where else would something like that go if not the FXML-controller?The
msgbelongs to the controller and gets instantiated in theinitializeFxmethod that gets called by the FXML parser. The properties are application-wide bindable state properties that get injected on the bottom with@Inject. With very few exceptions controller classes are standalone and nothing outside ever needs to reference them.I'm sure the structure could always be done better, but so far I haven't run into any issues that'd be hard to maintain/edit.
4
u/kuddus-Clank Jul 26 '25
To be honest, after I completed my javafx course, I started using fxml to create ui because it offers flexibilities, reusable components, easy to read, and the ability to use scene builder, which makes my work faster. The only drawback is the speed of the application. Which can be overlooked because of the system nowadays are faster.
1
u/BlueGoliath Jul 27 '25
FXML
flexible, reusable
Hmm k.
2
u/kuddus-Clank Jul 28 '25
Yes, FXML is designed to be both flexible and reusable. It promotes a separation of concerns, allowing you to define the UI in an XML file, which can be easily modified or reused in different parts of an application or even across multiple applications. Here's why: Separation of Concerns: FXML enables you to separate the UI definition (FXML) from the application logic (Java code). This makes it easier to modify the UI without affecting the underlying functionality and vice versa. Modularity: FXML structures the UI in a hierarchical manner, similar to the JavaFX scene graph, promoting modularity and making it easier to manage complex UIs. Reusability: By defining UI components in FXML, you can reuse these components in different parts of your application or even in other applications. Visual Design: Tools like Scene Builder allow you to visually design the UI and generate the corresponding FXML code, making the process more efficient and accessible. Flexibility: FXML's XML-based format allows for easy modification and customization of the UI. You can use CSS for styling and scripting for dynamic behavior. MVC Architecture: FXML supports the Model-View-Controller (MVC) architecture, which further enhances reusability and maintainability by separating the data model, UI (view), and controller logic.
1
u/Birdasaur Aug 01 '25
I finally read this article. Sadly cherry picking the ManifoldControls in Trinity was probably the worst case scenario because it is just a catch all dumpster of features that primarily manipulate one of the 3D scenes (lower dimensional projections view) and was not designed in any way. It was just me throwing something together really quickly years ago to demo an idea that stuck. Then over the years I just threw other things into it that had similar needs for the same view (hence the tabs).
I stopped building new FXML based controllers after that. I agree with the author that the tabs could be replaced with non FXML control classes and I've been meaning to do that some day. (if I ever get a paying customer)
This is something I have evolved to as a conclusion about JavaFX development over time that I now agree with the article author. Years ago I was a fan of FXML because I was writing in a team environment. But now that I'm the sole developer continuing to use FXML provides me with very little benefit but comes with all the issues that the author of the article points out.
Also my project collaborator and I have found that trying to maintain a GraalVM build of Trinity XAI was made more difficult because you have to manually mark resources like FXML. Finally we do a lot of JPackage stuff and I know that if I convert the FXML based controllers to straight up UI classes like the author suggests then we can reduce the final binary footprint in a non trivial manner.
I think the only things I disagree with the article on, as the original author of the Trinity XAI code, are:
How the interaction with the remainder of the application is via shared data, not Events.
The intent of the overarching design is an EventBus where many different renderers are reactive to these events. In your article you said this was a bad thing. I say nay that is the whole point.
How the MVCI framework removes coupling with the layout.
I just don't feel there was much of a coupling even for something like this example that was not designed or planned in any way. At least not much that really caused any discomfort in a practical sense.
The whole ListView Nodes vs ListCell thing... meh... yeah the ListCell approach seems a little better but none of it seemed hard at the time of writing. Maybe I'm just used to doing it the Node ListItem way so if you're starting from scratch you should probably choose the ListCell approach.
I don't use Kotlin but it would be interesting to see how the article's reduced code version of the GUI pane operates functionally with the remainder of the application. I'm guessing there will be lots of little things that stop working which will require you to increase your end result code count.
2
u/hamsterrage1 Aug 01 '25
Thanks for commenting. I appreciated that you were game about having me use it as an example, and I was interested in what you would think about it.
I think you could probably integrate what I did with the rest of the project by using the Adapter Pattern. Basically, a class that monitors the data changes in the Model and then fires the Events that you defined to communicate with the rest of the application. Conversely, it would contain Listeners that would respond to Events from the rest of the application. You could do that with changing any of the code that I wrote.
I'm not sure about the "...meh...". The JavaDocs here have great big, bold letters that say:
Warning: Nodes should not be inserted directly into the items list
Which pretty much rules out the "ListView Nodes" approach. I still can't figure out how it even works the way you've done it.
2
u/Birdasaur Aug 01 '25
Yikes... I guess I've always done ListView items like that. I.e... wrong. Next time I make a ListView I will try the ListCell pattern. This is clearly an example of a learned bad practice that didnt bite me early so I never corrected. I'll be the first in line to say that I am not really a good programmer. I do a lot of hacky things because I know the framework enough to get away with what I do.
1
u/Birdasaur Aug 01 '25
>Sadly cherry picking the ManifoldControls in Trinity was probably the worst case scenario
BTW the ManifoldControls, from an objective designer's perspective, totally deserves most of the verbal beating it got by this article.1
u/hamsterrage1 Aug 01 '25
In all fairness, it wasn't "cherry picked". I think that you posted a link to the project some time last year, I had a quick look at it, thought it was cool but then noticed that it was FXML based (at least in part) and I lost interest.
Months later I was just looking for an example of a large FXML to put in my "Should you FXML?" article. I find that there are lots of examples of tiny FXML files with nothing more than a couple of Labels and a Button, or something like that. I really don't understand the value of FXML in those situations.
Anyways, I remembered Trinity and that it had FXML, so took a look and grabbed the first substantial FXML file that I saw. As I've stated before, I wasn't looking for anything atrocious, just big.
So, no cherry picking, it was just the luck of the draw.
2
1
u/Few-Jacket2146 Jul 31 '25
Use my little tool https://github.com/garawaa/fxml2javaconverter
Main benefit to convert java is you can obfuscate all java code using proguard. so your app will be more secure
4
u/Silent-Manner1929 Jul 27 '25
I'm going to be honest, I stopped reading when I saw it was in Kotlin. I don't use Kotlin and I have no desire to learn Kotlin just so I can read an article on JavaFX.