Сообщение об ошибке
java.lang.IllegalStateException: Location is not set.
означает, что URL, который вы указали для конструктора FXMLLoader
, был null
. Метод Class.getResource(...)
автоматически возвращает null
, если указанный ресурс не может быть найден.
Это происходит из-за того, что имя ресурса, которое вы предоставляете своему методу loadFXML
и, в конечном итоге, App.class.getResource(...)
, неверно , Значение, которое вы указываете Class.getResource(...)
, представляет собой имя ресурса , подробности которого задокументированы здесь .
Имя ресурса формируется из "полностью определенного имени пакета класса, но преобразуйте все точки (.) в косую черту (/) "(см. ниже). Невозможно точно знать, что идет не так, по крайней мере, не увидев структуру папки buid и / или jar-файла, но это, вероятно, должно быть
scene = new Scene(loadFXML("/org/openjfx/primary"));
Поскольку ваши файлы F XML и класс, из которого Вы выполняете этот код в том же пакете, вы, вероятно, также можете обойтись, просто
scene = new Scene(loadFXML("primary"));
Некоторые соответствующие части этой документации:
Ресурсы, имена и контексты
Ресурс идентифицируется строкой, состоящей из последовательности подстрок, разделенных косыми чертами (/), за которыми следует имя ресурса. Каждая подстрока должна иметь действительный идентификатор Java. Имя ресурса имеет вид shortName или shortName.extension. И shortName, и расширение должны иметь идентификаторы Java.
Имя ресурса не зависит от реализации Java; в частности, разделителем пути всегда является sla sh (/). Тем не менее, реализация Java контролирует детали того, как содержимое ресурса отображается в файл, базу данных или другой объект, содержащий фактический ресурс.
Интерпретация имени ресурса относительно класса экземпляр загрузчика. Методы, реализованные в классе ClassLoader, выполняют эту интерпретацию.
...
Имена ресурсов
Общее соглашение для имени ресурса, используемого класс должен использовать полное имя пакета класса, но преобразовать все точки (.) в косые черты (/) и добавить имя ресурса в форме name.extension. Чтобы поддержать это и упростить обработку сведений о системных классах (для которых getClassLoader возвращает null), класс Class предоставляет два вспомогательных метода, которые вызывают соответствующие методы в ClassLoader.
Имя ресурса, присвоенное методу Class может иметь начальное начальное "/", которое идентифицирует его как "абсолютное" имя. Имена ресурсов, которые не начинаются с «/», являются «относительными».
Так что "/org.openjfx/primary"
не является допустимым именем ресурса, поскольку "org.openjfx"
не является действительным Java идентификатором.
В вашей структуре обратите внимание, что org.openjfx
- это не папка , а пакет . Среда IDE и инструмент сборки преобразуют ее в иерархию папок в файловой системе и, в конечном итоге, в файл jar, при этом структура пакета-подпакета заменяется папками и подпапками. Таким образом, в структуре вашего исходного кода у вас будет папка "java" с подпапкой "org", подпапка "openjfx", а также исходные файлы Java для классов в пакете org.openjfx
. В папке «resources» у вас также будет подпапка «org», подпапка «openjfx» и файлы ресурсов, которые вы создали (включая файл FMXL).
Инструмент сборки ( либо Maven, либо только ваша IDE) распознает указанные c исходные папки; они настроены в вашем случае, чтобы включить «java» и «ресурсы». Когда приложение собрано, объединение структур в исходных папках воссоздается в цели сборки; здесь это просто приводит к одной папке org
и подпапке openjfx
. Любые исходные файлы Java компилируются в файлы классов; любые другие файлы просто копируются. Наконец, все это упаковано в jar-файл (который, по сути, является просто zip-архивом).
Если вы найдете файл jar в файловой системе (по умолчанию Maven поместит его в папку «target», которая находится рядом с вашей папкой «sr c»), вы можете просмотреть его содержимое с помощью
jar -tf Oblig1-1.0-SNAPSHOT.jar
(я думаю, что Oblig1-1.0-SNAPSHOT.jar
- это имя сгенерированного файла JAR, но, очевидно, при необходимости измените его). Вы должны увидеть структуру папок, которую я обрисовал в общих чертах, и вывод должен включать
/org/openjfx/App.class
/org/openjfx/PrimaryController.class
/org/openjfx/SecondaryController.class
/org/openjfx/primary.fxml
/org/openjfx/secondary.fxml
(та же структура должна существовать в папке target/classes
, хотя, опять же, наименование и местоположение папки зависит от настроек Maven.)
Кроме того, вам не следует использовать org.openjfx
для собственных имен пакетов и идентификаторов групп Maven; используйте что-то определенное c для себя или своей организации.