How to reference javafx fxml files in resource folder?
Asked Answered
L

3

50

I am creating a javafx GUI application and my project is a maven configured project. I want to be able to reference my fxml files like this in my controllers:

FXMLLoader.load(getClass().getResource("main.fxml")); 

Where my main.fxml file is located in the src/main/resources folder and my controller is in the src/main/java folder. How do i go about doing this? My src/main/resources folder is in the build path and i am able to call a .properties file that is in the src/main/resources folder from a class in the src/main/java folder.

Edit

I attempted to place the fxml file in the corresponding directory of the main resources folder:

enter image description here

but i still got an error.

Lyssa answered 26/10, 2013 at 4:13 Comment(0)
T
127

Generic Resource Lookup Information

This answer discusses FXML location lookup, which is really just a subset of the generic resource lookup task in Java. The resource location is passed by the calling program as input to the FXMLLoader, so the resource lookup itself is part of your calling application code and not the FXMLLoader.

For thorough coverage of generic resource information (including recommended troubleshooting steps) for Java/JavaFX applications, please refer to:

Also useful, is the Eden coding resource guide:


Example usage

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/main.fxml"));
Parent content = loader.load(); 

Location resolution options

  1. Put all of your fxml in the src/main/resources directory.

    loader.setLocation(getClass().getResource("/main.fxml"));
    
  2. Put all of your fxml in a src/main/resources/fxml directory.

    loader.setLocation(getClass().getResource("/fxml/main.fxml"));
    
  3. Place fxml in a corresponding resource directory; e.g. src/main/resources/com/mycompany/myapp.

    loader.setLocation(getClass().getResource("main.fxml")); 
    

The last option assumes that the class from which you are loading the fxml is in the same relative location in the corresponding Java source hierarchy. For example, you might invoke the last load command from source com/mycompany/myapp/Main.java.

FXMLLoader usage recommendations

  1. Instantiate an FXMLLoader via new FXMLLoader() rather than using the static methods on the FXMLLoader.

    • The static methods become confusing when you want to get values (like instantiated controllers) out of a loader.
  2. Set the location on the instantiated FXMLLoader and call load() rather than loading from a stream using load(stream).

    • Setting a URL based location on the loader allows for resolution of relative resources loaded in fxml and css files. Relative resources do not resolve for a stream based constructor.
  3. To derive a location based upon a class, use getClass().getResource(), as it is URL based, rather than getClass().getResourceAsStream() which is stream based.

IDE and Build Settings

Ensure that your IDE or build tool is copying the fxml files from the resource directory to the build output directory. For understanding Intellij settings for this, see: How to convert a normal java project in intellij into a JavaFx project.

A note on Java Jigsaw modular applications

See:

Specifically, don't write:

ComboBoxStyling.class.getClassLoader()
    .getResource("/css/styleclass.css");

Instead write:

ComboBoxStyling.class
    .getResource("/css/styleclass.css"); 

That is, get the resource from the class directly rather, NOT from the class loader. If you get resources from a class loader rather than the class, then there are additional restrictions on lookup based upon the module configuration. These restrictions can be hard to understand, see the documentation for the Class and ClassLoader getResource methods for information if needed.

Theatheaceous answered 26/10, 2013 at 5:10 Comment(4)
You are still using the static method in your example. You need to call getResourceAsStream instead of getResourceAdamec
Thanks Felix, fixed and clarified the answer. 3 years and 28 upvotes and nobody had pointed out this anomaly in the original answer before ;-)Theatheaceous
All this time, it was failing because I did not put / before the start folder. I.e. getClass().getResource("fxml/main.fxml").Palaestra
Quick note for NetBeans users, you can add existing folders to src by right clicking your project directory > properties > select "sources" > select the folder you want to add to source > Add Folder. So if you already have a folder with your fxml that you are trying to reference, you can just add the folder and call the fxml files with their relative path.Niki
I
7

You are using FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource("main.fxml") ); to load your main.fxml. This requires the main.fxml and the java class loading it in same directory/path. If you want to load an fxml file from a path/location different from the java class loading it, you need to use relative path. As @jewelsea mentioned above, you may use the relative path using / character before your main.fxml. So the code that will make it work for you in your case is

FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource("/main.fxml") );
Insomnolence answered 27/10, 2013 at 5:37 Comment(1)
Actually this is the simple answer to the problem, makes sense too once you think about it . The path is relative to the source file where were are calling the FXMLLoader().Pomfret
M
0

Open your resources folder in the file explorer of your operation system. Here you will see that you have created a "dominion.application" folder instead of an "application" folder inside of a "dominion" folder. Because of this the "MainController" class is placed in a different package as the fxml file.

Marijuana answered 19/11, 2013 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.