0

I have a simple JavaFX project. It consists from:

  • src/app/Main.java
  • src/app/controller/MainController.java
  • src/app/controller/SecondaryWindowController.java
  • src/app/view/Main.fxml
  • src/app/view/SecondaryWindow.fxml

The controller MainController.java has method (handler of press button):

public void openWindow(ActionEvent event) {
    Pane root = null;
    try {
        System.out.println("URL: " + getClass().getResource("../view/SecondaryWindow.fxml"));
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/SecondaryWindow.fxml") );
        root = loader.load();
    }
    catch(Exception e) {
        e.getMessage();
        e.printStackTrace();
    }
    if (root != null) {
        Scene scene = new Scene(root,400,100);
        Stage secStage = new Stage();
        secStage.setTitle("Secondary Window");
        secStage.setScene(scene);
        secStage.show();
    }
}

Code getClass().getResource("../view/SecondaryWindow.fxml") return right URL if I run project from compile files. But it return null if I run project from JAR-file.

I compile files using:

javac -d bin src\app\Main.java
javac -d bin src\app\controller\*.java
XCOPY src\app\view\*.fxml bin\app\view /s /e /d /y

and run compile files using:

java -classpath bin app.Main

Catalog bin has similar structure of files:

  • bin/app/Main.class
  • bin/app/controller/MainController.class
  • bin/app/controller/SecondaryWindowController.class
  • bin/app/view/Main.fxml
  • bin/app/view/SecondaryWindow.fxml

And I create JAR-file using:

jar cvfm SimpleFXMLApp.jar manifest.mf -C bin app

Manifest.mf

Manifest-Version: 1.0
Created-By: Denys Selivanov
Main-Class: app.Main

Why relative path doesn't work in JAR-file and getClass().getResource("../view/SecondaryWindow.fxml") return null ? How repair that?

One of the problem's solves is keep controllers and views files in one catalog and use relative path "SecondaryWindows.fxml", but I want keep my structure files of project.

And you can download my project here. This link will be access 30 days.

1 Answers1

2

I see the vote to close that says it's a duplicate of this Q&A, but I don't think it explains the specifics of .., so here you go:

.. works on resources on the filesystem, because .. is an actual entry on the filesystem, that points to parent directory. But that does not exist within jars, so it won't work to point to "parent package" when your classes & resources are packaged in a jar.

Solution: if you can accept the dependency from your controller class to Main class, you can do this instead:

Main.class.getResource("view/SecondaryWindow.fxml")

In any case you'll need to either reference a class that is high enough in the packages hierarchy, or use an absolute path from root package (getClass().getClassLoader().getResource("app/view/SecondaryWindow.fxml") in your case apparently).

Hugues M.
  • 19,846
  • 6
  • 37
  • 65
  • Both variants (relative path from highest class and absolute path from root package) work. But getClass().getClassLoader().getResource(/app/view/SecondaryWindow.fxml) don't work, instead I use getClass().getResource(/app/view/SecondaryWindow.fxml). Thank you. – Денис Селиванов Aug 19 '17 at 07:32
  • Ah, yes in last example there was a mistake, I edited to fix – Hugues M. Aug 19 '17 at 07:47
  • Oh, the [new duplicate question](https://stackoverflow.com/questions/34755630/javafx-location-is-not-set-error) has a better answer than the original I mentioned, it explains why `..` does not work here. – Hugues M. Aug 19 '17 at 07:51