When I open the following FXML file in IntelliJ:
<VBox alignment="CENTER" spacing="20.0" stylesheets="@/org/kordamp/bootstrapfx/bootstrapfx.css" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo2.HelloController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
<Label fx:id="welcomeText" />
<Button onAction="#onHelloButtonClick" styleClass="alert-danger" text="Hello!" />
</VBox>
I get this error:
Note that in this project I have the BootstrapFX library defined as a dependency in Maven.
I'm assuming that stylesheets="@/org/kordamp/bootstrapfx/bootstrapfx.css" should look into the proper JAR dependency in my Maven external libraries and get the CSS file from there...
Of course, when I run the application from IntelliJ, it yields this error (the css is not found on the classpath):
Caused by: javafx.fxml.LoadException: Invalid resource: /org/kordamp/bootstrapfx/bootstrapfx.css not found on the classpath
So how can I specify in the stylesheets attribute of the FXML (or in my project's configuration) a path to a CSS file located inside a JAR file?
(I know that I can extract the css from the JAR file, copy it in my resources/ folder and include it in the FXML file specifying the relative path to my external css, and it works like a charm, but I would like to know how to do it directly from the JAR file)
Given it appears BootstrapFX is modularized, my guess is that the stylesheet is encapsulated. That means code from outside the library's module cannot access the resource, because the library does not declare the necessary
opens
directives. Though this should only take effect if BootstrapFX is being loaded as a named module (i.e., on the module-path). Otherwise, I would expect this to work:Note: In FXML, the
@
prefix is the "location resolution operator". It means to treat the subsequent path as being relative to the current FXML file. I doubt the stylesheet is located atorg/kordamp/bootstrapfx/bootstrapfx.css
relative to your FXML file.That said, it looks like the intended approach is to use
BootstrapFX#bootstrapFXStylesheet()
in code. That method returns a string URL pointing to the stylesheet. The URL mechanism "bypasses" the encapsulation issue. That means you should consider adding the stylehsheet in the controller. For example:However, it is possible to call the
bootstrapFXStylesheet()
method via FXML usingfx:factory
. For example: