I have been digging into this issue, and as this
thread comes up when searching these errors, so I think it's worth waking up.
I assume you are using IntelliJ, and have added the JavaFx SDK to your project as a library (you did that with Gradle).
The issue is, as Knute said, with the Java 9 modules. All code in Java 9+ is part of a module. When you do not provide a module descriptor, it runs in a module called the unnamed module, which reads all named modules and exports all of its packages. The main issue here is that code in the unnamed module can't access the JavaFx libraries.
In this case you have a few options:
1 - Use the JavaFx plugin for
Maven or Gradle to run your project
2 - Add a module descriptor to your project
3 - Override the module behaviour using VM arguments
First method — Using the JavaFx plugin:
You are using Gradle, so you can run your project using the JavaFx plugin. See
here for an example. You can do the same
with Maven.
I’d also like to show how to get things to run via the
IDE, which is pretty easy too.
Second method — Adding a module descriptor:
This is also very easy and a good way to go. Java has been modular for a couple of years now, and it's time to modularize!
Add a module-info.java file to your project. Your IDE should have an option to create a module descriptor for your project. Open it up and it should look like this:
JavaFx works by reflection, but reflective access of a module's contents is denied by default. We need to use the opens keyword to open our new module up to reflection.
We also need to read to read the JavaFx modules needed. You are using javafx.fxml, and I'm sure you will also use javafx.controls. We need to show our dependency on them with the requires keyword.
This is how our module descriptor will look:
(For more info about modules and the module descriptor, take a look at this
Oracle article)
Third method — Adding VM arguments:
This is pretty much a more ‘hacky’ way of doing the same thing. Your code should be compiling fine. To run it, though, we need to tweak the run configuration.
We need to put the JavaFx modules on the module path manually this way. This we can do by opening up Run > Edit Configurations and adding ‘--module-path /<path to JavaFx SDK>/lib/’ to the VM options.
We’ll also need access to them. The biggest issue with having your code in the unnamed module is that some modules don’t become part of its module graph (the modules it has access to), regardless of whether they are on the module path or not. We’ll have to add the JavaFx modules we need to the your module’s module graph manually. For this we’ll have to use the java tools --add-modules option to add javafx.fxml and javafx.controls. We’ll add this to the VM options after what we have already put: ‘--add-modules javafx.controls,javafx.fxml’. Make sure you don’t put a space between the two.
(You can read up to the
java tool and its options here.)
Note that the command that IntelliJ is using to run your program (printed at the top of the console) contains ‘--add-modules javafx.base,javafx.graphics’. That is why you could run your program until you started using fxml.
Now everything should be set and ready to go!