JavaFX - Jak przekazać obiekt do innego kontrolera

0

Cześć.

Głowie się nad tym nie pierwszą godzinę. Posiadam prostą aplikację imitującą bank. Mam w niej kontroler X(MainLoginPaneController) który ma 2 metody. Pierwsza metoda sprawdza czy w tablicy jest dana osoba i zwraca tą osobę. Druga metoda obsługuje przycisk logowania. Jeżeli osoba ta jest w tablicy z odpowiednim loginem i hasłem to przełącza na inną scenę. I teraz problem pojawia się taki:

-Jak do tej innej sceny(MainLoggedPaneController) przekazać ten obiekt (osobę)?
-Załóżmy że przekazałem obiekt, ale podczas np. tworzenia tabeli (GridPane) w jakiejś metodzie z informacjami o nim, dostane błąd bo kontroler wywołał już metoda public void initialize() z metodą która posiada pusty obiekt.

Dodaję że sceny przełączają się, a nie tworzą jakby nowe okienka (Rozwiązanie to znalazłem na forum).


public class main extends Application {
    private Bank bank;

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


    public void start(Stage primaryStage) throws IOException {
        //Creating bank
        bank = new Bank();

        // getting loader and a pane for the first scene.
        FXMLLoader firstPaneLoader = new FXMLLoader(getClass().getResource("/fxml/loginFXML/mainLoginPane.fxml"));
        Parent firstPane = firstPaneLoader.load();
        Scene firstScene = new Scene(firstPane, 400, 300);

        // getting loader and a pane for the second scene
        FXMLLoader secondPageLoader = new FXMLLoader(getClass().getResource("/fxml/registerFXML/mainRegisterPane.fxml"));
        Parent secondPane = secondPageLoader.load();
        Scene secondScene = new Scene(secondPane, 400, 300);

        // getting loader and a pane for the third scene
        FXMLLoader thirdPageLoader = new FXMLLoader(getClass().getResource("/fxml/loggedUserFXML/mainLoggedPane.fxml"));
        Parent thirdPane = thirdPageLoader.load();
        Scene thirdScene = new Scene(thirdPane, 400, 300);

        //FIRST
        MainLoginPaneController firstPaneController = (MainLoginPaneController) firstPaneLoader.getController();
        firstPaneController.setSecondScene(secondScene);
        firstPaneController.setThirdScene(thirdScene);
        firstPaneController.bankOpen(bank);
        System.out.println(bank);


        //SECOND
        MainRegisterPaneController secondPaneController = (MainRegisterPaneController) secondPageLoader.getController();
        secondPaneController.setFirstScene(firstScene);
        secondPaneController.bankOpen(bank);

        //THIRD
        MainLoggedPaneController thirdPaneController = (MainLoggedPaneController) thirdPageLoader.getController();
        thirdPaneController.setFirstScene(firstScene);

        primaryStage.setScene(firstScene);
        primaryStage.show();


    }


}
public class MainLoginPaneController implements bankOpening {

    @FXML
    private ButtonLoginPaneController buttonLoginPaneController;
    @FXML
    private ContentLoginPaneController contentLoginPaneController;

    //Scene switching
    private Scene secondScene;
    private Scene thirdScene;
    private Person person;


    public void setThirdScene(Scene thirdScene) {
        this.thirdScene = thirdScene;
    }

    public void setSecondScene(Scene scene) {
        secondScene = scene;
    }

    public void openThirdScene(ActionEvent actionEvent) {
        Stage primaryStage = (Stage) ((Node) actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(thirdScene);
    }

    public void openSecondScene(ActionEvent actionEvent) {
        Stage primaryStage = (Stage) ((Node) actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(secondScene);
    }

    //Sharing a bank object
    private Bank bank;
    public void bankOpen(Bank mainBank) {
        this.bank = mainBank;
    }



    //Methods

    public void initialize() {
        buttonRegister();
        buttonLogin();
    }


    private void buttonRegister() {
        buttonLoginPaneController.getRegisterButton().setOnAction(this::openSecondScene);
    }


    private void buttonLogin() {
        buttonLoginPaneController.getLoginButton().setOnAction(event -> {
            try {
                person = checkLoginAndPassword();
                System.out.println(person.getLogin());
                openThirdScene(event);


            } catch (NullPointerException e) {
                System.out.println(e.getMessage());
            }
        });
    }

    private Person checkLoginAndPassword() {
        ArrayList<Person> k = new ArrayList<>(bank.users.values());
        for (int i = 0; i < k.size(); i++) {
            if (k.get(i).getLogin().equals(contentLoginPaneController.getLoginTextField().getText()))
                if (k.get(i).getPassword().equals(contentLoginPaneController.getPasswordPasswordField().getText()))

                    return k.get(i);
        }
        throw new NullPointerException("Błędny login i/lub hasło");

    }

}
public class MainLoggedPaneController implements bankOpening {

    @FXML
    private ButtonLoggedPaneController buttonLoggedPaneController;
    @FXML
    private ContentLoggedPaneController contentLoggedPaneController;
    

    private Scene firstScene;
    private Bank bank;

    public void setFirstScene(Scene scene) {
        firstScene = scene;
    }

    public void openFirstScene(ActionEvent actionEvent) {
        Stage primaryStage = (Stage) ((Node) actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(firstScene);
    }

    public void bankOpen(Bank mainBank) {
        this.bank = mainBank;
    }

    public void initialize() {
        logoutButton();

    }

    private void logoutButton() {
        buttonLoggedPaneController.getLogoutButton().setOnAction(logoutEvent -> {
            openFirstScene(logoutEvent);
        });
    }



}
0

Spróbuj sobie komunikację między kontrolerami ogarnąć za pomocą EventBus'a z Guavy albo GreenRobot: https://github.com/greenrobot/EventBus z czego ten drugi ma "buga" że odbiorcą sygnału nie może być klasa z dostępem pakietowym.

0

Spróbuje to ogarnąć, ale nie wiem czy poradzę sobie, aż tak jeszcze nie czuje się na siłach.

0

Jeśli to jest tylko aplikacja, w której uczysz się progrmowania i JavyFX, to możesz też sobie stworzyć swoją klasę z kontekstem w postaci np. singletonu.

Tu taki najprostszy przykład:

public final class ApplicationContextHolder {
  private static final ApplicationContextHolder INSTANCE = new ApplicationContextHolder();

  private final ApplicationContext applicationContext;

  private ApplicationContextHolder() {
    this.applicationContext = new ApplicationContext();
  }
  
  public static ApplicationContext getApplicationContext() {
    return INSTANCE.applicationContext;
  }
  
}

public class ApplicationContext {
  private Osoba osoba; // tu ew. mógłbyś mieć nie po prostu atrybut Osoba, a jakiś inny, bardziej precyzyjny kontekst, 
                       // np. AuthContext czy tam SecurityContext i dopiero wewnątrz mieć osobę, principal czy jak to tam zwać
  
  public void setOsoba(Osoba osoba) {
    this.osoba = osoba;
  }
  
  public Osoba getOsoba() {
    return osoba;
  }
}

Jeśli Ci się chce, możesz także popatrzeć, jak to jest rozwiązane w np. Spring Security - pakiet org.springframework.security.core.context.

0

Dzięki za odpowiedź sprawdzę sobie to potem. Aktualnie znalazłem inne rozwiązanie, najzwyczajniej w świecie z klasy startowej gdzie tworze sceny to przekazuje FXMLloadery do poszczególnych klas. W tych klasach tworzę coś typu " MainLoggedPaneController mainLoggedPaneController = loader.getController();", a następnie wywołuje metodę mainLoggedPaneController.initialize(user);. Dzięki temu przekazuje Od razu usera, a cała logika odbywa się już w danym kontrolerze.

1 użytkowników online, w tym zalogowanych: 0, gości: 1