Исключение при загрузке данных из xml

222
09 января 2018, 14:08

Я создал 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
Answer 1

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/... Папка используется чтобы отделить ресурсы логически от исходного кода.

READ ALSO
Почему Presenter не пересоздается вместе с Activity

Почему Presenter не пересоздается вместе с Activity

Не могу понять как работает MvpPresenterПочему когда Activity пересоздается, то MvpPresenter все еще живет

216
Как связать таблицы между собой?

Как связать таблицы между собой?

Пишу проект для андроид устройств и появилась необходимость в использовании баз данныхИмеется бд в которой 3 таблицы:

227
Как создать Label в Android Studio &amp; libGDX

Как создать Label в Android Studio & libGDX

Сейчас пишу игруРаботаю в Android Studio

187
Подскажите метод в java android, который бы открывал и воспроизводил видеофайлы в моем плеере?

Подскажите метод в java android, который бы открывал и воспроизводил видеофайлы в моем плеере?

Здравствуйте! Я начинающий программист в области java на андроидпишу сейчас приложение на андроид - видеоплеер

245