在 JavaFX 中,尝试从嵌套控制器调用主控制器的方法会出现 NullPointerException

问题描述 投票:0回答:1

我目前正在构建一个简单的应用程序来读取 .txt 文件并可视化场景上的 3D 点。

这是我当前的代码:

----------Main.java----------

import controllers.ImportMenuController;
import controllers.MainController;
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 {

        FXMLLoader mainLoader = new FXMLLoader(getClass().getResource("FXML/Main.fxml"));
        Parent root = mainLoader.load();
        MainController mainController = mainLoader.getController();

        FXMLLoader importMenuLoader = new FXMLLoader(getClass().getResource("FXML/ImportMenu.fxml"));
        importMenuLoader.load();
        ImportMenuController importMenuController = importMenuLoader.getController();

        importMenuController.setMainController(mainController);

        Scene scene = new Scene(root, 1920, 1080);

        primaryStage.setTitle("Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

---------- Main.fxml----------

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

<?import javafx.scene.control.*?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.*?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="controllers.MainController">
    <top>
        <MenuBar>
            <fx:include source="FileMenu.fxml" fx:id="fileMenu"/>
        </MenuBar>
    </top>
    <center>
        <Group fx:id="centerGroup"/>
    </center>
</BorderPane>

----------FileMenu.fxml----------

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

<?import javafx.scene.control.*?>

<Menu xmlns:fx="http://javafx.com/fxml" 
fx:controller="controllers.FileMenuController" text="File">
    <MenuItem text="New"/>
    <MenuItem text="Open"/>
    <MenuItem text="Save"/>
    <MenuItem text="Save As"/>
    <SeparatorMenuItem/>
    <fx:include source="ImportMenu.fxml" fx:id="importMenu"/>
</Menu>

----------ImportMenu.fxml------------

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

<?import javafx.scene.control.*?>

<Menu xmlns:fx="http://javafx.com/fxml" text="Import" 
fx:controller="controllers.ImportMenuController">
    <MenuItem text="Model"/>
    <MenuItem text="Solver Deck" onAction="#onImportSolverDeck"/>
    <MenuItem text="Geometry"/>
</Menu>

----------MainController.java----------

package controllers;

import javafx.fxml.FXML;
import javafx.scene.Group;

import javafx.scene.control.Menu;
import node.Node;

public class MainController {

    @FXML private Menu fileMenu;
    @FXML private FileMenuController fileMenuController;
    @FXML private Group centerGroup;

    @FXML
    public void initialize() {
    }

    public void addNodeToScene(double x, double y, double z, int ID) {
        Node node = new Node(x, y, z, ID);
        centerGroup.getChildren().add(node.getSphere());
    }
}

----------文件菜单控制器----------

package controllers;

import javafx.fxml.FXML;
import javafx.scene.control.Menu;

public class FileMenuController {

    @FXML private Menu importMenu;
    @FXML private ImportMenuController importMenuController;

    @FXML
    public void initialize() {
    }
}

----------导入菜单控制器----------

package controllers;

import javafx.fxml.FXML;
import javafx.stage.FileChooser;

import java.io.*;

public class ImportMenuController {

    private MainController mainController;

    @FXML
    public void initialize() {
    }

    public void setMainController(MainController mainController) {
        this.mainController = mainController;
    }

    @FXML
    public void onImportSolverDeck() {

        try {
            FileChooser fileChooser = new FileChooser();
            fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text File (.txt)", "*.txt"));
            File selectedFile = fileChooser.showOpenDialog(null);
            if (selectedFile != null) {
                femLoader(selectedFile);
            }
        } catch (IOException e) {
            System.out.println("Unable to read the selected file: " + e.getMessage());
        }
    }

    private void femLoader(File femFile) throws IOException {

        try (BufferedReader reader = new BufferedReader(new FileReader(femFile))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("GRID")) {
                    String[] parts = line.split("\\s+");
                    int ID = Integer.parseInt(parts[1]);
                    double x = Double.parseDouble(parts[2]);
                    double y = Double.parseDouble(parts[3]);
                    double z = Double.parseDouble(parts[4]);
                    mainController.addNodeToScene(x, y, z, ID);
                }
            }
        }
    }
}

Node.java 类只是 Point3D 的扩展,添加到已经很长的帖子中是没有意义的。 场景加载正常,但每当我单击 .txt 文件时,就会出现

NullPointerException
。 特别是在选择文件后,
this.mainController
突然变成了
null
。 我真的很难在这里找到问题,任何帮助将不胜感激。

java javafx nullpointerexception
1个回答
0
投票

据我了解,

FXMLLoader mainLoader
FXMLLoader importMenuLoader
是完全独立的对象。
mainLoader
将负责子组件的初始化,因此通过调用
importMenuLoader
,您将获得另一个实例,并且您在此实例上调用
setMainController

我的JavaFX知识有点生疏,但据我记得,你必须将

MainController
直接注入到
ImportMenuController
您不需要设置器,这应该可以解决问题:

@FXML
private MenuController menuController;
© www.soinside.com 2019 - 2024. All rights reserved.