JavaFX 如何从其他阶段控制器访问控制器?
JavaFX how to access Controller from other stage Controller?
我的应用程序有两个阶段。第一阶段是主要阶段,它在应用程序启动时启动。我已经为这个 Stage FXML 文件和控制器准备如下:
- Launcher.fxml 的 LauncherController(父级),其中我有一个带有一些选项卡的 TabView,并包含在 fx:id 每个选项卡和 TopMenuButtons 的 FXML 文件中。
- WaitingMode.fxml 的 WaitingModeController(子)(包含在 Launcher.fxml 中)
- NewConversation.fxml 的 NewConversationController(子)(包含在 Launcher.fxml 中)
- TopMenuButtons.fxml 的 TopMenuButtonsController(子)(包含在 Launcher.fxml 中)
启动器控制器:
public class LauncherController implements Initializable {
@FXML
private TabPane wholeTabPane;
@FXML
private Tab waitingModeTab;
@FXML
private Tab newConversationTab;
@FXML
private WaitingModeController waitingModeFXMLController;
@FXML
private NewConversationController newConversationFXMLController;
@Override
public void initialize(URL location, ResourceBundle resources) {
TabPane tabPane = wholeTabPane;
}
public void openNewConverationTab(){
wholeTabPane.getSelectionModel().select(newConversationTab);
}
}
我在 TopMenuButtons 中有一个按钮,其方法是 openAssisstantStage(),可打开新的小舞台:
public class TopMenuButtonsController {
public void openAssisstantStage(ActionEvent event) {
Stage stage = (Stage)((Button)event.getSource()).getScene().getWindow();
stage.setIconified(true);
FXMLLoader loadAssisstant = new FXMLLoader(this.getClass().getResource(FXMLFilePaths.ASSISSTANT_FXML));
Parent assisstant = null;
try {
javafx.geometry.Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
assisstant = (Parent) loadAssisstant.load();
Stage waitingStage = new Stage();
waitingStage.setTitle("Asystent");
waitingStage.setScene(new Scene(assisstant));
waitingStage.setAlwaysOnTop(true);
waitingStage.initStyle(StageStyle.UNDECORATED);
waitingStage.setX(primaryScreenBounds.getMaxX() - 500);
waitingStage.setY(primaryScreenBounds.getMinY());
waitingStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对于这个阶段,我还有 FXML 文件和控制器 (AssisstantController)。只有 2 个按钮 - 第一个按钮应该打开上一个 Stage 并关闭当前,但是第二个按钮也应该打开 prevoius Stage,关闭当前 并且还打开我的 TabView 中的特定选项卡并执行其他操作逻辑例如。获取实际的本地日期:
public class AssisstantController {
@FXML
private Button maxWindowButton;
@FXML
private Button goToNewConversationButton;
@FXML
public void openMainWindow(ActionEvent actionEvent) {
Stage stage = (Stage) ((Button) actionEvent.getSource()).getScene().getWindow();
stage.close();
Launcher.getMainStage().setIconified(false);
}
@FXML
public void goToNewConversation(ActionEvent actionEvent) {
FXMLLoader loader = new FXMLLoader(getClass().getResource(FXMLFilePaths.LAUNCHER_FXML));
LauncherController controller = (LauncherController)loader.getController();
controller.openNewConverationTab();
Stage stage = (Stage) ((Button) actionEvent.getSource()).getScene().getWindow();
stage.close();
Launcher.getMainStage().setIconified(false);
//do other logic...
}
}
出于同样的原因,我不能 initialize in LauncherController my AssisstantController, because assisstant isn't launcher's child. I can't use Mediator pattern。
打开上一个 Stage 工作正常,但是当我尝试从 FXMLLoader 访问 LauncherController 时,我遇到了由
引起的 NullPointerException
controller.openNewConverationTab();
在 AssisstantController 中。我不知道它应该如何工作...我想打开 previous Stage 并将特定选项卡设置为活动状态。
带有 main() 和 start() 方法的我的启动器:
public class Launcher extends Application {
public static final String APP_NAME = "...";
public static Double AppVersion = 1.1;
private static Stage mainStage;
public static Stage getMainStage() {
return mainStage;
}
public void openMainStage(Stage mainStage) {
this.mainStage = mainStage;
}
@Override
public void start(Stage primaryStage) throws Exception {
openMainStage(primaryStage);
FXMLLoader loadMainScene = FXMLLoaderSingleton.getInstance().getLoader();
loadMainScene.setLocation(this.getClass().getResource(FXMLFilePaths.LAUNCHER_FXML));
Pane mainScenePane = loadMainScene.load();
Scene mainScene = new Scene(mainScenePane);
primaryStage.setScene(mainScene);
primaryStage.setTitle(APP_NAME);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
一种方法是
创建一个 class 例如 'StageConfig'
public class StageConfig
{
private static TopMenuButtonsController tmbc = null;
private static AssisstantController ac = null;
public static void setTopMenuButtonsController(TopMenuButtonsController tmbc_val)
{
StageConfig.tmbc = tmbc_val;
}
public static TopMenuButtonsController getTopMenuButtonsController()
{
return StageConfig.tmbc;
}
public static void setAssisstantController(AssisstantController ac_val)
{
StageConfig.ac = ac_val;
}
public static getAssisstantController getController()
{
return StageConfig.ac;
}
}
现在为示例初始化它
public class TopMenuButtonsController implements Initializable
{
@Override
public void initialize(URL location, ResourceBundle resources)
{
StageConfig.setTopMenuButtonsController(this);
}
}
现在你可以在任何你想使用的地方使用控制器。
StageConfig.getTopMenuButtonsController().SOMENODE.
我的应用程序有两个阶段。第一阶段是主要阶段,它在应用程序启动时启动。我已经为这个 Stage FXML 文件和控制器准备如下:
- Launcher.fxml 的 LauncherController(父级),其中我有一个带有一些选项卡的 TabView,并包含在 fx:id 每个选项卡和 TopMenuButtons 的 FXML 文件中。
- WaitingMode.fxml 的 WaitingModeController(子)(包含在 Launcher.fxml 中)
- NewConversation.fxml 的 NewConversationController(子)(包含在 Launcher.fxml 中)
- TopMenuButtons.fxml 的 TopMenuButtonsController(子)(包含在 Launcher.fxml 中)
启动器控制器:
public class LauncherController implements Initializable {
@FXML
private TabPane wholeTabPane;
@FXML
private Tab waitingModeTab;
@FXML
private Tab newConversationTab;
@FXML
private WaitingModeController waitingModeFXMLController;
@FXML
private NewConversationController newConversationFXMLController;
@Override
public void initialize(URL location, ResourceBundle resources) {
TabPane tabPane = wholeTabPane;
}
public void openNewConverationTab(){
wholeTabPane.getSelectionModel().select(newConversationTab);
}
}
我在 TopMenuButtons 中有一个按钮,其方法是 openAssisstantStage(),可打开新的小舞台:
public class TopMenuButtonsController {
public void openAssisstantStage(ActionEvent event) {
Stage stage = (Stage)((Button)event.getSource()).getScene().getWindow();
stage.setIconified(true);
FXMLLoader loadAssisstant = new FXMLLoader(this.getClass().getResource(FXMLFilePaths.ASSISSTANT_FXML));
Parent assisstant = null;
try {
javafx.geometry.Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
assisstant = (Parent) loadAssisstant.load();
Stage waitingStage = new Stage();
waitingStage.setTitle("Asystent");
waitingStage.setScene(new Scene(assisstant));
waitingStage.setAlwaysOnTop(true);
waitingStage.initStyle(StageStyle.UNDECORATED);
waitingStage.setX(primaryScreenBounds.getMaxX() - 500);
waitingStage.setY(primaryScreenBounds.getMinY());
waitingStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对于这个阶段,我还有 FXML 文件和控制器 (AssisstantController)。只有 2 个按钮 - 第一个按钮应该打开上一个 Stage 并关闭当前,但是第二个按钮也应该打开 prevoius Stage,关闭当前 并且还打开我的 TabView 中的特定选项卡并执行其他操作逻辑例如。获取实际的本地日期:
public class AssisstantController {
@FXML
private Button maxWindowButton;
@FXML
private Button goToNewConversationButton;
@FXML
public void openMainWindow(ActionEvent actionEvent) {
Stage stage = (Stage) ((Button) actionEvent.getSource()).getScene().getWindow();
stage.close();
Launcher.getMainStage().setIconified(false);
}
@FXML
public void goToNewConversation(ActionEvent actionEvent) {
FXMLLoader loader = new FXMLLoader(getClass().getResource(FXMLFilePaths.LAUNCHER_FXML));
LauncherController controller = (LauncherController)loader.getController();
controller.openNewConverationTab();
Stage stage = (Stage) ((Button) actionEvent.getSource()).getScene().getWindow();
stage.close();
Launcher.getMainStage().setIconified(false);
//do other logic...
}
}
出于同样的原因,我不能 initialize in LauncherController my AssisstantController, because assisstant isn't launcher's child. I can't use Mediator pattern。
打开上一个 Stage 工作正常,但是当我尝试从 FXMLLoader 访问 LauncherController 时,我遇到了由
引起的 NullPointerExceptioncontroller.openNewConverationTab();
在 AssisstantController 中。我不知道它应该如何工作...我想打开 previous Stage 并将特定选项卡设置为活动状态。
带有 main() 和 start() 方法的我的启动器:
public class Launcher extends Application {
public static final String APP_NAME = "...";
public static Double AppVersion = 1.1;
private static Stage mainStage;
public static Stage getMainStage() {
return mainStage;
}
public void openMainStage(Stage mainStage) {
this.mainStage = mainStage;
}
@Override
public void start(Stage primaryStage) throws Exception {
openMainStage(primaryStage);
FXMLLoader loadMainScene = FXMLLoaderSingleton.getInstance().getLoader();
loadMainScene.setLocation(this.getClass().getResource(FXMLFilePaths.LAUNCHER_FXML));
Pane mainScenePane = loadMainScene.load();
Scene mainScene = new Scene(mainScenePane);
primaryStage.setScene(mainScene);
primaryStage.setTitle(APP_NAME);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
一种方法是 创建一个 class 例如 'StageConfig'
public class StageConfig
{
private static TopMenuButtonsController tmbc = null;
private static AssisstantController ac = null;
public static void setTopMenuButtonsController(TopMenuButtonsController tmbc_val)
{
StageConfig.tmbc = tmbc_val;
}
public static TopMenuButtonsController getTopMenuButtonsController()
{
return StageConfig.tmbc;
}
public static void setAssisstantController(AssisstantController ac_val)
{
StageConfig.ac = ac_val;
}
public static getAssisstantController getController()
{
return StageConfig.ac;
}
}
现在为示例初始化它
public class TopMenuButtonsController implements Initializable
{
@Override
public void initialize(URL location, ResourceBundle resources)
{
StageConfig.setTopMenuButtonsController(this);
}
}
现在你可以在任何你想使用的地方使用控制器。
StageConfig.getTopMenuButtonsController().SOMENODE.