Getting started with FX isn’t as easy as it sounds, and the library has undergone a number of breaking changes (as far as instructions on how to set it up goes) in recent years. It used to be bundled with Java, which meant you didn’t have to do much more than download and install Java (I think).
Then it became its own library — which actually made me concerned for its fate, given that it seemed like Oracle was distancing itself, but there seems to be a vigorous community and the separation makes a lot of sense, allowing development to proceed independently and also freeing Java developers from having to include it all over the place. (A lot of effort seems to be going toward modularizing Java and making it smaller, and I heartily approve of that.)
UPDATE: IntelliJ 2021.2 introduced JavaFX project templates that actually work out of the box and don’t require adding all the directories for development, testing and execution.
The first issue I had in this process was that I already had several Javas on my system. I primarily work in Clojure these days, and about the only breakage I’ve ever had in Clojure comes from Java’s shakeup (between versions 7 and 8?) that removed some things from the standard library. Otherwise Clojure is pretty indifferent to which Java is used.
But I would also try out things like TornadoFX, Kotlin’s interface to JavaFX, and in the past I’ve used other systems that were very partial to which Java VM you used, and installing one VM would break things elsewhere. (This is why a lot of modern Java apps bundle their VM with them.)
Defeat, Sort Of
My hope was to be able to switch between Java versions from the command line. I knew I could write a script to alter my PATH from one version of Java to another, and I did so. But Java doesn’t just depend on the PATH, it also uses the JAVA_HOME environment variable.
Well, good, I thought. I’ll change the JAVA_HOME variable and use that in the PATH, and I can flip between them. No dice, at least on Windows. The instant you open the command line, the JAVA_HOME variable is read and plugged into the path. Changing it after does nothing.
So, for now I’m just using Java 15 exclusively, and keeping away from straying into toolkits that require something else. I’m sure this is a solvable problem but it’s not worth the effort right now.
I’m using JetBrains IntelliJ for my IDE. I’ve got an all-products license because it’s ridiculously cheap (although it’s up to $650 now, renewal gets cheaper every year, it seems like) and it’s wonderfully comprehensive. If I have some Python to do or C#, I can just grab their specific IDEs, and very often there’s a plugin for the less popular languages. (I pay a little bit each year for a Cursive license for Clojure development, as well.) The free “Community” version should work for all that follows, however.
I couldn’t quite use The Definitive Guide to set up the IDE because things had changed enough in the 2–3 years since it was written, but it (and the official “getting started” page) got me through the process. It’s not very difficult, but if you doing it by rote (as I was) and something goes wrong, you’re stuck (which is always the way in technology).
Right now the official page works with the current versions of everything (Java 15, JavaFX 15, IJ Ultimate 2020.3) and this is the process I use to set up a new project.
- Create a new JavaFX project. Select File|New|New Project from the menus, and this will bring up a dialog of possible project types. Select JavaFX from the list on the left and press Next. (You can also opt for different Java SDKs, if you have them, but I’m sticking with 15.)
- Fill in the project name and location on the next page and click “Finish”. I keep all of my coding projects in a directory called “projects” (unimaginatively enough) and I try to group all my toy/test projects in a subdirectory under that so they don’t clutter the main directory. So, all my JavaFX projects are in ~/projects/jfx. (I’m calling this project “fxgames”.)
- Rather refreshingly, IJ sets you up with a very simple project structure: You get a main directory with the “.iml” file (“fxgames.iml”, e.g.) which is one of IJ’s settings files, and a subdirectory “.idea” for its other settings. We can ignore these. Our project consists otherwise of a “src” directory containing a “sample” sub-directory and three files: Main, Controller and sample.fxml.
- Observe, however, that IJ has put red squiggles under the whole project, then under src, sample and finally Main. This is because it can’t compile the project because it can’t compile Main.
- If you look at Main, you’ll see it can’t compile it because it can’t import the JavaFX libraries. It seems odd to me that this isn’t part of the project setup and I wouldn’t be surprised to see this change in the future, but for now, to fix, you have to go into File|Project Structure and click on Libraries under Project Settings (on the left side). The rest of the dialog should be basically blank (because you’ve added no libraries yet).
- Click on the + at the top and you’ll see the options “Java”, “from Maven” and “Kotlin/JS”. We want “Java.” Then navigate to the directory where you downloaded the JavaFX SDK and in that directory select the “lib” subdirectory. So, I put my JavaFX SDK in C:\javafx-sdk-15.0.1, and I select C:\javafx-sdk-15.0.1\lib. If you get it right, the next dialog will say “Library ‘lib’ will be added to the selected modules” with your project name underneath. If you get it wrong, IJ will start asking questions about what it is that’s in this library.
- When you’ve got it right, the main area of the Project Structure “Libaries” pane will show “lib” in the middle pane and on the right there’ll be an entry for “Classes” and “Sources”. Press “OK”, and all the red will vanish from your project, indicating you can compile it.
And compile it you can! But it won’t run! Give it a try and you’ll see that you need JavaFX runtime components, which you don’t have, apparently. This first set of steps, noted above, only sets up the libraries for development, not for actually running the final project.
Keep in mind that we can automate some of this stuff, but until I really have a good feel for what’s going on, I like to go through the steps manually, so I haven’t done that yet. (The above seven steps, for example, are much harder to explain than to do, once you know them. And we’ll need to do them again to import other libraries into our projects.)
To run the app, we also have to set up our run/debug configuration so that it knows where the Java components are. This requires going into different settings. IJ lets you set up a bunch of different environments in which to run, debug, test or otherwise try out your code. The default JavaFX app starts with a “Main” environment — this is the one that doesn’t work when you try to run it.
If you click on the “Main” drop down, it will have an option for “Edit configurations”. Click on that and you’ll get a big ol’ settings dialog that allows you to specify parameters you want to run the program with and (more to the point for our task) VM options. There’s a little link on the right-hand side that reads “Modify options” and if you click on that, it will reveal even more things you can tweak.
One of the options in that menu is “Add VM options”. Click on that and you’ll be returned to the main dialog with a new visible entry for VM options: In that you specify where to find the JavaFX controls for running. For my projects, I put:
--module-path C:\javafx-sdk-15.0.1\lib --add-modules javafx.controls,javafx.fxml
in that place. You should replace “C:\javafx-sdk-15.0.1\lib” with the appropriate path on your machine. The add-modules switch can be the same.
Now, you can run it:
This window looks even more boring on a web page where the borders aren’t visible. But fear not, this is our black triangle, and from here things get easier and more fun.