我已经研究了几个小时了,即使有很多关于“多个控制器”的问题,但没有一个解决方案可以解决我的问题。我不知道我是否只是错误地构建我的程序,所以我需要一些输入。
我有一个“MainView”(App
课程,其中包含AppView
和AppController
)和一个“SubView”(SubView
和SubViewController
)。在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()