JavaFX, как получить доступ к контроллеру из другого этапа контроллера? - PullRequest
0 голосов
/ 24 октября 2018

Мое приложение имеет две стадии.Первая стадия является основной и запускается при запуске приложения.Я подготовил для этого Stage FXML файлы и контроллеры следующим образом:

  1. LauncherController (родительский) для Launcher.fxml, где у меня есть TabView с некоторыми вкладками и включены FXX-файлы fx: id для каждой вкладкии для TopMenuButtons.
  2. WaitingModeController (дочерний) для WaitingMode.fxml (включен в Launcher.fxml)
  3. NewConversationController (дочерний) для NewConversation.fxml (включен в Launcher.fxml)
  4. TopMenuButtonsController (дочерний) для TopMenuButtons.fxml (входит в Launcher.fxml)

LauncherController:

    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 кнопки - 1-ая кнопка должна открыть предыдущую стадию и закрыть текущий, но 2-ая кнопка также должна открыть предварительную стадию, закрыть текущий И также открыть определенную вкладку в моем TabView и выполнить некоторую другую логику, например.получить фактическое LocalDate:

    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...
}
}

Я не могу инициализировать в LauncherController мой AssisstantController , потому что ассистент не является потомком запуска.Я не могу использовать шаблон Mediator по той же причине.

Открытие предыдущей стадии работает нормально, но когда я пытаюсь получить доступ к LauncherController из FXMLLoader, у меня возникает исключение NullPointerException, вызванное

controller.openNewConverationTab();

в AssisstantController.Я понятия не имею, как это должно работать ... Я хочу открыть предыдущую стадию и установить конкретную вкладку как активную.

Мой лаунчер с методами 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);
}

}

1 Ответ

0 голосов
/ 24 октября 2018

Один из способов сделать это - создать класс для примера '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.
...