Я создал JavaFX проект и в контроллере главного окна реализую метод, в котором при нажатии на кнопку должно создаться новое модальное окно, но при при загрузке данных из xml файла выбрасывается исключение. Что не так в моем коде?
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("fxml/sample.fxml"));
primaryStage.setTitle("Телефонная книга");
primaryStage.setScene(new Scene(root, 600, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
package sample.controllers;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
public class MainController {
public void removePeople(ActionEvent event) {
System.out.println("remove");
}
public void addPeople(ActionEvent event) throws IOException {
Stage stage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("fxml/modalWindowAddPeople.fxml"));
stage.setScene(new Scene(root, 200, 200));
stage.setTitle("Добавление контакта");
stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(false);
stage.initOwner(((Node) event.getSource()).getScene().getWindow());
stage.show();
}
}
sample.xml
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="382.0" prefWidth="602.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controllers.MainController">
....
modalWindowAddPeople.fxml
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox fx:controller="sample.controllers.ModalWindowAddPeople" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="197.0" prefWidth="421.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
Исключения:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
....
Caused by: java.lang.reflect.InvocationTargetException
....
Caused by: java.lang.NullPointerException: Location is required.
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3207)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at sample.controllers.MainController.addPeople(MainController.java:22)
... 58 more
Class.getResource возвращает ресурс по имени. Метод ищет файл по пути относительно класса, от которого метод вызывается.
Например, класс Main находится в пакете sample, файл sample.xml находится в пакете sample/fxml. Соответственно, из класса Main поиск ресурса по относительному пути срабатывает корректно:
Parent root = FXMLLoader.load(getClass().getResource("fxml/sample.fxml"));
Ошибка же происходит при втором обращении. Класс MainController находится в пакете sample.controllers. Соответственно, при вызове из него:
Parent root = FXMLLoader.load(getClass().getResource("fxml/modalWindowAddPeople.fxml"));
метод будет искать ресурс в расположении sample/controllers/fxml/modalWindowAddPeople.fxml, в то время как файл находится в пакете sample/fxml.
Пути решения:
прописывать каждый раз относительный путь от класса, из которого вызывается метод:
getClass().getResource("../fxml/modalWindowAddPeople.fxml")
обращаться к ресурсам через слэш по абсолютному пути:
getClass().getResource("/sample/fxml/modalWindowAddPeople.fxml").
Судя по всему, Вы используете для сборки Maven. По-умолчанию, при сборке файлы из каталога src/resources перемещаются в корень (поведение по-умолчанию может быть переопределено настройками), соответственно, если файл лежит в папке src/resources/fxml, то к нему можно обратиться по абсолютному пути /fxml/... Папка используется чтобы отделить ресурсы логически от исходного кода.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости