JavaFX - 加载/创建多个控制器

时间:2018-01-04 19:53:58

标签: javafx controllers

我已经研究了几个小时了,即使有很多关于“多个控制器”的问题,但没有一个解决方案可以解决我的问题。我不知道我是否只是错误地构建我的程序,所以我需要一些输入。

我有一个“MainView”(App课程,其中包含AppViewAppController)和一个“SubView”(SubViewSubViewController)。在App中,我将mainView加载为primaryStage并加载AppController。我创建了一个stageManager类来处理不同的视图。我的问题是:我在哪里以及如何创建/加载subViewController

public class App extends Application {

    private Stage primaryStage;
    private AnchorPane rootLayout;
    private AppController appController;

    MainModel model = new MainModel();
    StageManager stageManager;

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("App");

        initRootLayout();
        appController.initModel(model);
        appController.setStageManager(stageManager);
    }

    public void initRootLayout() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("mainView.fxml"));
            rootLayout = (AnchorPane) loader.load();
            appController = loader.<AppController>getController();

            Scene scene = new Scene(rootLayout);
            primaryStage.setScene(scene);
            primaryStage.show();

            stageManager = new StageManager(primaryStage, rootLayout, appController);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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




public class AppController implements Initializable {

    private MainModel model;
    private StageManager stageManager;

    @FXML
    private Button btn;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        stageManager.changeScene("subView.fxml");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }   

    public void initModel(MainModel model) {
        this.model = model;
    }

    public void setStageManager(StageManager stageManager){
        this.stageManager = stageManager;
    }
}


public class StageManager {

    private Stage primaryStage;
    private AnchorPane rootLayout;
    private AppController appController;

    public StageManager(Stage primaryStage, AnchorPane rootLayout, AppController appController){
        this.primaryStage = primaryStage;
        this.rootLayout = rootLayout;
        this.appController = appController;
    }

    public void changeScene(String scene){
        try {
            Parent parentPane = FXMLLoader.load(getClass().getResource(scene));
            primaryStage.getScene().setRoot(parentPane);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


public class SubController implements Initializable {

    private MainModel model;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }    

    public void setModel(MainModel model){
        this.model = model;
    }    
}


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

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" prefHeight="524.0" prefWidth="850.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.SubController">
   <children>
      <Label fx:id="lbl" layoutX="52.0" layoutY="13.0" prefHeight="38.0" prefWidth="214.0" text="just a label">
         <font>
            <Font name="Consolas" size="24.0" />
         </font>
      </Label>
   </children>
</AnchorPane>

我尝试了以下内容来加载其他控制器: 首先,我尝试使用与加载appController相同的方式(因为它可行),但不将视图设置为scene。所以在initRootLayout()方法中我简单地添加了:

FXMLLoader subloader = new FXMLLoader();
subloader.setLocation(getClass().getResource("subView.fxml"));
subController = loader.<SubController>getController();

这不起作用。实际上发生了一件非常奇怪的事。当我尝试从subController调用方法时,我得到了NullPointerException。调试显示正在加载subController,但在加载后它会消失并且subController Object只是“null”。那是为什么?

我在阅读有关此方法后尝试的下一件事是将subController添加为FXML变量。在AppController我添加@FXML private SubController subController;AppController的{​​{1}}方法中,我尝试从控制器拨打电话:

initialize()

在这种情况下,我收到 @Override public void initialize(URL url, ResourceBundle rb) { subController.setModel(model); } ,但实际上它指的是我在NullPointerException课程中调用appController.initModel(model);的行。即使这条线在我不使用App时工作正常。 所以,我非常困惑,我认为我需要一个全新的结构。任何有用的帮助将不胜感激! :)

编辑: 这似乎有效:我将subController方法更改为:

changeScenes()

0 个答案:

没有答案