Загрузка файла из ресурсов при использовании модулей

Я пытаюсь загрузить файл FXML из каталога ресурсов, чтобы отобразить окно JavaFX, однако, что бы я ни делал, я не могу найти правильный способ ссылки на ресурс.

Моя структура каталогов выглядит следующим образом:

src
    main
        java
            gui
                App.java
            module-info.java
        resources
            MainWindow.fxml
out
    production
        classes
            // All compiled classes
        resources
            MainWindow.fxml

Содержимое module-info.java следующее:

module MyApp {
    requires javafx.controls;
    requires javafx.graphics;
    requires javafx.fxml;
    exports gui;
}

Я пытаюсь загрузить файл MainWindow.fxml в App.java следующим образом: getClass().getResource("/MainWindow.fxml");

Я пытался использовать имена MainWindow.fxml и /MainWindow.fxml, однако оба возвращают значение null. Как видно из структуры каталогов, копируется и содержимое ресурсов, поэтому они должны быть доступны во время выполнения. Каталог ресурсов помечен как таковой в IntelliJ. Я использую Gradle для управления зависимостями.

Как я могу загрузить файлы из каталога ресурсов?

Вот мой файл build.gradle:

plugins {
    id 'application'
    id 'java'
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

group 'MyApp'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.11

javafx {
    modules = [
            'javafx.controls',
            'javafx.graphics',
            'javafx.fxml'
    ]
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation group: 'junit', name: 'junit', version: '4.12'

    implementation 'org.openjfx.javafx-controls:11.0.1'
    implementation 'org.openjfx.javafx-fxml:11.0.1'
    implementation 'org.openjfx.javafx-graphics:11.0.1'
}

person tofiffe    schedule 02.01.2019    source источник
comment
Может быть: App.class.getResource("../resources/MainWindow.fxml");?   -  person Flown    schedule 02.01.2019
comment
Я пробовал ../resources/MainWindow.fxml, /resources/MainWindow.fxml, resources/MainWindow.fxml, ни один из них не возвращает ресурс.   -  person tofiffe    schedule 02.01.2019
comment
Для начала вы должны открыть свой проект в модуле fxml, например opens gui to javafx.fxml, как в этом пример. Используете ли вы плагин Gradle для JavaFX? Можете ли вы показать свой файл build.gradle?   -  person José Pereda    schedule 02.01.2019
comment
@JoséPeda Я добавил файл build.gradle. Я также добавил оператор opens, но я думаю, что это может быть какая-то другая проблема, поскольку файл не может быть загружен до выполнения любого связанного с ним JavaFX.   -  person tofiffe    schedule 02.01.2019
comment
Вам не нужна часть implementation, плагин сделает это за вас. Также не нужно добавлять javafx.graphics, он добавляется элементами управления. Что касается вашей проблемы, у вас есть исключение? Можете ли вы опубликовать трассировку стека? Пробовали ли вы запустить пример, на который я ссылался ранее, он у вас работает?   -  person José Pereda    schedule 02.01.2019
comment
Да, образец работает (тот, где элементы управления добавлены программно). Я получаю, что местоположение не установлено. исключение, но я точно указал, что getResource() возвращает null   -  person tofiffe    schedule 02.01.2019
comment
@tofiffe, не могли бы вы попробовать собрать jar ($ ./gradlew jar также может потребоваться указать основной класс: jar { manifest { attributes 'Main-Class': 'gui.App' } }) и получить доступ к ресурсу, используя: InputStream asStream = App.class.getModule().getResourceAsStream("MainWindow.fxml");   -  person caco3    schedule 02.01.2019
comment
Если в вашем проекте есть трассировка стека (из-за того, что местоположение не указано), добавьте его в вопрос. Вы говорите, что связанные образцы с FXML вам не подходят?   -  person José Pereda    schedule 02.01.2019
comment
@caco3, создав банку, я получаю Error: Could not find or load main class gui.App Caused by: java.lang.NoClassDefFoundError: javafx/application/Application   -  person tofiffe    schedule 02.01.2019
comment
Вам не нужно создавать банку только для того, чтобы это работало... Во-первых, в банке не будет классов JavaFX...   -  person José Pereda    schedule 02.01.2019
comment
@JoséPeda О, да, ты прав. Запуск основного метода, который пытается получить доступ к ресурсу из IntelliJ, создает NullPointerException, но встроенный jar не   -  person caco3    schedule 03.01.2019
comment
О... Кажется, мне удалось запустить его в Idea: добавление apply plugin: 'idea' idea { module { inheritOutputDirs = true } } к build.gradle сработало для меня... (см. этот вопрос)   -  person caco3    schedule 03.01.2019
comment
@ caco3 добавление плагина идеи и inheritOutputDirs сработало! Можете ли вы опубликовать это как ответ, чтобы я мог принять его?   -  person tofiffe    schedule 03.01.2019
comment
Проблема здесь, похоже, в том, что ресурсы не находятся в out/production/classes, следовательно, они не находятся в модуле. Если классы и ресурсы упакованы в JAR-файл, тогда должно работать приложение App.class.getResource(/MainWindow.fxml) — косая черта в начале указывает на его полное имя ресурса. Единственный способ исправить взорвавшийся корпус — это пропатчить модуль, чтобы добавить в модуль содержимое out/production/resources, то есть --patch-module MyApp=out/production/resources.   -  person Alan Bateman    schedule 03.01.2019
comment
@AlanBateman Я бы сказал, что если классы и ресурсы упакованы в файл jar таким особым образом, приложение даже не запустится, так как невозможно указать подкаталог в файле jar в качестве элемента пути к классу.   -  person Holger    schedule 10.01.2019