NullPointerException загружает граф сцены из FXML, интегрированный с Spring - PullRequest
0 голосов
/ 31 января 2019

Я хочу создать контроллер для моего приложения JavaFX, которое автоматически загружает файл FXML "view.fxml" в член "Родительский корень" и принимает аргументы конструктора (в этом примере "String message").

Я сделал так, чтобы все работало нормально, но затем я попытался создать экземпляр DemoController, используя Spring, и получил «NullPointerException: Root не может быть нулевым».Это раздражает меня, потому что создание экземпляра bean-компонента с использованием Spring, кажется, работает просто отлично, и все же он не загружает FXML правильно.Мое единственное предположение, что структура каталогов может быть испорчена, но я не могу это исправить, и я был бы очень признателен за любую помощь:)

Main.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        DemoController myController = (DemoController) context.getBean("myController");

        primaryStage.setScene(new Scene(myController.getRoot()));
        primaryStage.setTitle("Game of Life");
        primaryStage.show();    

        ((ClassPathXmlApplicationContext) context).close();
    }
}

FXMLController.java

import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;


public abstract class FXMLController implements Initializable {

    protected Parent root;

    protected String fxmlFilePath;

    public void afterPropertiesSet() throws Exception {
        loadFXML();
    }

    protected final void loadFXML() throws IOException {    
        FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFilePath));
        loader.setController(this);
        this.root = loader.load();
    }

    public Parent getRoot() {
        return root;
    }

    public void setFxmlFilePath(String fxmlFilePath) {
        this.fxmlFilePath = fxmlFilePath;
    }
}

DemoController.java

import java.net.URL;
import java.util.ResourceBundle;

public class DemoController extends FXMLController {

    public DemoController(String message) {
         System.out.println(message);
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        System.out.println("initializing");     
   }

}

Beans.xml

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id = "myController" class = "DemoController">
      <constructor-arg value = "message"/>
      <property name = "fxmlFilePath" value = "/view.fxml"/>
   </bean>

</beans>

view.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane xmlns:fx="http://javafx.com/fxml/1">
    <!-- TODO Add Nodes -->
</AnchorPane>

структура каталогов

  • src
    • Beans.xml
    • view.fxml
    • (пакет по умолчанию)
      • DemoController.java
      • FXMLController.java
      • Main.java

консольный вывод

message
Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: Root cannot be null
    at javafx.scene.Scene.<init>(Scene.java:336)
    at javafx.scene.Scene.<init>(Scene.java:194)
    at Main.start(Main.java:21)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    ... 1 more
Exception running application Main

Краткий обзор кода:

  • Main устанавливает среду JavaFX и использует Spring для создания экземпляра DemoController.Он отображает граф сцены, заданный контроллером.
  • FXMLController - это абстрактный класс, который инкапсулирует загрузку файла FXML и предоставляет методы получения для графа сцены (getRoot ()).
  • DemoController расширяет FXMLController и не добавляет много.
  • Beans.xml предоставляет Spring необходимую информацию о конфигурации для контроллера.
  • view.fxml имеет только AnchorPane и практически пуст.

1 Ответ

0 голосов
/ 31 января 2019

Вы не реализуете InitializingBean, поэтому afterPropertiesSet никогда не вызывается.Реализация этого интерфейса должна решить проблему:

public abstract class FXMLController implements Initializable, InitializingBean {

    ...

    @Override
    public void afterPropertiesSet() throws Exception {
        loadFXML();
    }

    ...

}
...