Most of the time, you’ll want to load resources in using Java’s inbuilt functions. It’s just generally simpler, and often Java does the heavy lifting for you.

If fact, loading resources into CSS, Java and FXML files all involves leveraging Java’s and JavaFX’s URL-resolution.

Loading a Resource in JavaFX:

File you’re loading intoContextCorrect procedure
CSSurl() functionRules for URL resolution and leading slash characters
FXMLUsing <fx:include> to include external FXML filesRules for URL resolution and leading slash characters
FXMLLoading resource such as image, or CSS stylesheetRules for location resolution operator @
JavagetClass().getResource(String location)Rules for URL resolution and leading slash characters

Loading resources into an FXML file:

Once you get into more complex applications, maybe with multilingual support, you might start to work with resource bundles. To do that, we modify the label to take a message from a resource bundle, and display that text instead:

File you’re loading intoContextCorrect procedure
FXMLReference to resource bundle e.g. text="%greeting"Use % operator and align name with resource key
FXML file:
<Label alignment="CENTER" maxWidth="300" text="%greeting"/>
Result:

That might seem quite foreign if you’ve never used a resource bundle, but check out my guide on dependency injection using FXML if you want to know more. It’s a complete guide on creating custom views using constructor and field injection. Field injection is the one you want for using the resource bundle!

What you’ll get from this tutorial

With all of that in mind, in each section, I’ll go through the three ways to get resources into JavaFX in detail. In each section, I’ll show you how to correctly assign the file path to the JavaFX interpreter to reach the resource you need.

Feel free to hop ahead to the section you need now, and bookmark the page for later, for when you need the rest.

  1. Loading resources in Java code
  2. Getting resources into a CSS file
  3. Referencing resources in FXML

Loading resources as a URL

In the table at the start, there were three situations where you might want to load a resource using a URL:

  1. Through the url() function in a CSS file
  2. Specifying a UR in the FXML file’s <fx:include> tag
  3. Using the get getClass().getResource(String location) method in Java code

JavaFX calculates the location or a resource URL by considering two things:

  1. The content of the location String.
  2. The presence, or absence of a leading slash “/”.

Note: The optional leading "/" does not have a literal file-system meaning. It’s a flag used by Java to determine where to start the search for a resource.

That’s it! Values that begin with a leading slash character are treated as relative to the classpath (that’s the root of your resources folder if you’re using one). Whereas, locations with no leading slash are considered relative to the path of the current document (that could be a Java class, a CSS file or an FXML document).

Check out the drop-downs to see how to apply these rules for navigating in cases of Java code, CSS and FXML:

Java Code:

Resources such as images and FXML files can be loaded into a JavaFX application using Java code by invoking the getClass().getResource(String location) method, passing in the location of the resource.

Loading a resource in Java code

We’re going to concentrate here on loading a resource through the getClass().getResource() method. That generates a URL that can be used to load files, images and other resources.

A great example of this is when you’re loading in an FXML file to the FXMLLoader.

URL fxmlLocation = getClass().getResource("sample.fxml");
FXMLLoader loader = new FXMLLoader(fxmlLocation);

Getting the error “Location is not set” is one of the most common errors here, and it’s always because the String you pass to getResource() isn’t quite correct.

With that in mind, the String you provide to getResource() depends on how you’ve organised your resources (images, CSS files etc). I think there are probably three ways you could organise them:

Ways to organise resources:
  1. By type, in subdirectories like “images” and “css”
  2. By project, in subdirectories like “auth” and “rendering”
  3. By both project and type

In each section below, I want to dive into each possibility, and build up the URL string to reach the resources we need.

I’ll also take a special look at applying this to CSS, where we’re often navigating between adjacent directories, rather than from a root directory down.

We’ll use the example of loading an FXML file into getClass().getResources() method call, but the String we generate will be the same regardless.

a. Loading resources in when they’re organised by type

Organising resources by type is something I really like to do. To do this, you have to modify the string you pass into the getResource() method to signal to JavaFX that you want to navigate to your

As an example, one of the first things I always do is add a logo. It helps make it look slightly more professional, and conforms with user’s expectations.

Resources organised by type:
Creating the correct location String:

To find the right String to pass getResource() we see:

  1. The img and fxml directories are in the root of the project, so we’ll start the resource name with "/".
  2. I want to navigate to the image directory "img" and then to my resource EdenCodingIcon.png. To achieve this, I add "img/EdenCodingIcon.png"

So, the full method call is:

getClass().getResource(/img/EdenCodingIcon.png)

b. Loading resources in when they’re organised by package

Organising by package is also useful for separating different views based on their function. For example, we might have multiple packages for the main app, and user logins.

Resources organised by package:
Creating the correct location String:

If we exclude the leading “/” from getResource() method call, JavaFX knows that we want to search for the document relative to the package we’re currently in. If we’re making this call from Main.java, we’re in the com.edencoding package. This will be the start of the search.

URL fxmlLocation = LoginController.class.getResource("login.fxml");
FXMLLoader loader = new FXMLLoader(fxmlLocation);

Here’s how getResource() will work out the location:

  1. The sample.fxml file is in package "com.edencoding", so we’ll start the resource name without a leading "/". This will automatically start the search in “com.edencoding” because Main.java is in that package.
  2. I want to find my resource in the package root, so I don’t need to navigate through any directories.
  3. To specify the file I want, I add "login.fxml"

So, the full string is:

login.fxml

This can seem really counter-intuitive, because you’d think if you were navigating between packages, you’d need to specify more information. However, by leaving out the leading “/”, we’re telling JavaFX to add that information in for us.

c: Loading resources in when they’re organised by package and type

In this case, let’s extend the example above and store the login.fxml file inside a directory to separate it from the other images I need in the login View.

Resources organised by both type and package:

I’ve collapsed the java folder, but it has the same basic structure as before.

Creating the correct location String:

For one last time, we find the right string to pass getResource() by:

  1. The login.fxml file is in package "auth", so we’ll start the resource name without a leading "/". This will automatically start the search in “auth” because LoginController is in that package.
  2. I want to navigate to the fxml directory and to my resource login.fxml.
  3. To achieve this, I add "img/login.fxml"

So, the full string is:

img/login.fxml

CSS Code:

Resources such as font and image files can be loaded into a CSS script using the url() function, which accepts a URI and passes this to the CSS interpreter. The <uri> CSS data type can be defined as either a local file or as a web-resource.

Loading a resource in CSS

Whenever you define an image, or a font, you’ll be specifying the resource using the url() function.

/* Loading fonts */
@font-face {
    src: url("Poppins.ttf"),
}
.root {
    -fx-font-family: "Poppins";
}

/* Web resource */
    -fx-background-image: url(https://edencoding.com/image.png)

/*  Local file  */
    -fx-background-image: url(../folder/styles.css)

It’s worth noting you’ll need to load the font into the application in Java code first. The CSS interpreter won’t be able to access the font if you haven’t done this already.

Warning!

URLs in CSS are really common. However, the CSS parser isn’t as smart as the Java URL resolver. You can still do absolutely everything you need, but it comes with a warning: including a leading slash to start at the resources route can only be used to select files directly in your resources folder.

There are multiple ways to navigate to a file in CSS using the url() function

Navigating from the resources folder outwards doesn’t seem to work. If you take a look at the URLConverter in the javafx.css.converter package, we can immediately see it’s designed to navigate from the CSS file location:

/**
 * Converts a parsed value representing  URL to a URL string that is
 * resolved relative to the location of the stylesheet.
 * The input value is in the form: {@code url("<path>")}.
 *
 * @since 9
 */
public final class URLConverter extends StyleConverter<ParsedValue[], String> {
...
}

So, whenever you call the url() function in the CSS file, bear in mind it’s most sensible to navigate from the location of the CSS file.

Creating the correct location String:

This time, we find the right string to pass url() by:

  1. The img and css directories are next to each other, so we’ll start the resource name with "../" to navigate back up to the resources folder.
  2. I want to navigate back down to the image directory "img" and then to my resource EdenCodingIcon.png. To achieve this, I add "img/EdenCodingIcon.png"

So, the full method call is:

url('../img/EdenCodingIcon.png')

In the CSS file, that might look something like this:

.logo{
    -fx-background-image: url('../img/EdenCodingIcon.png');
}
FXML Code:

The only time a URL will be required in loading resources into an FXML file is when specifying an FXML document to use as an element in the current view. In this case, the FXML file must be reference using the <fx:include source="..."> tag.

Loading a resource in FXML

Just to recap, there are two circumstances where you might need to load resources into an FXML file:

File you’re loading intoContextCorrect procedure
FXMLUsing <fx:include> to include external FXML filesRules for URL resolution and leading slash characters
FXMLLoading resource such as image, or CSS stylesheetRules for location resolution operator @

In both situations, the FXML parser uses the same URL-resolution rules. The only difference is that when you’re using <fx:include>, you don’t have to use the “@” operator.

JavaFX’s own introduction to FXML is pretty awful, so I’ll go through each in turn.

<fx:include>
<fx:include source="lab.fxml"/>
Image
<Image url="@../img/image.png">

Like the CSS interpreter, it also comes with a warning.

Warning!

Including a leading slash to start at the resources route can only be used to select files directly in your resources folder. Trying to navigate from the resources folder outwards will result in an error

<fx:include source="/fxml/MyLabel.fxml"/>

Results in the following error:

Caused by: javafx.fxml.LoadException: Cannot resolve path: /fxml/MyLabel.fxml
/C:/code/examples/target/classes/fxml/LabelExample.fxml:9

Similarly, trying to do so with an image request like this:

<Image url="@/img/EdenCodingIcon.png"/>

Results in the following error:

Caused by: javafx.fxml.LoadException: Invalid resource: /img/EdenCodingIcon.png not found on the classpath
/C:/code/examples/target/classes/fxml/LabelExample.fxml:14

Like the CSS interpreter, the FXML interpreter is also designed to navigate from the current file location.

Creating the correct location String:

OK, so let’s load in a style sheet first, and then use the <fx:include> tag to load in a custom view element. Here’s the project we’ll be working with:

In the following snippets, we’ll be writing code in the combinedView.fxml file.

Loading a stylesheet.

Let’s navigate from the FXML file combinedView.fxml to include the stylesheet contentViewer.fxml.

The CSS file we want isn’t in the resources root, so we cannot navigate to it by including a leading slash. Instead:

  1. The resource requires the location resolution operator, so we’ll start with "@".
  2. The css and fxml directories are next to each other, so we’ll begin the navigation with "../" to navigate back up to the resources folder.
  3. I want to navigate back down to the image directory "css" and then to my resource styles.css. To achieve this, I add "css/styles.css"

So, the stylesheets attribute will look like this:

<AnchorPane stylesheets="@../css/styles.css" xmlns="http://javafx.com/javafx/10.0.2-internal">

...

</AnchorPane>
<fx:include>

To include a custom element in our FXML file, we can use the <fx:include> tag. Again, we’ll be writing code in the combinedView.fxml file. Let’s navigate from the FXML file combinedView.fxml to include the element contentViewer.fxml.

  1. The viewElements directory is inside the fxml directory, so we’ll include "./" to start the path inside the current directory. We need to include the “.” because otherwise Java thinks we’re trying to flag that we should start from the resources root and we’ll get an error.
  2. I want to navigate down to the directory "viewElements" and then to my resource contentViewer.fxml.
  3. To achieve this, I add "viewElements/contentViewer.fxml"

So, the full <fx:include> tag is:

<fx:include source="./viewElements/contentViewer.fxml")/>

That’s it for loading URLs. It doesn’t matter whether you’re using CSS, FXML, or Java code. In each case, use the same logic to work out whether to include the leading slash, and the work through the directory structure systematically.

Just remember the CSS and FXML interpreters aren’t quite as clever, and navigating from the resources root outwards can throw errors.

Conclusions

Most internal resources in JavaFX should be loaded using the URL-resolver of either the Java class, or the CSS- or FXML-parsers. This guarantees that Java works out where the file is, rather than you having to!

For larger applications, default values for FXML elements can be loaded using a Resource Bundle. If you’re looking for where to go next, I’ve made a complete guide here on how to do just that. Field injection is the one you want for using the resource bundle.