1

I am building a JavaFX application with multiple screen, and therefore multiple FXML files with their controllers. The initialize method of the controller is already done when the application starts for all FXML files.

I have a lockscreen, where a user needs to type a password to enter the next screen. When the password is correct, the name of the employee is retrieved and the main menu screen is loaded.

I would like to pass the name of the user to a label in the main menu screen, but I can not use the initialize method of the controller, since it is already called.

Is there a way to perform an action on showing a FXML screen, to enable me to pass the string between controllers?

Any help is much appreciated!

ps. If you would like to see the code, comment below.

EDIT (for better understanding)

Below you can find the code:

Main.java

public class Main extends Application {

public static String screen1ID = "loginscherm";
public static String screen1File = "Lockscreen.fxml";
public static String screen2ID = "mainmenu";
public static String screen2File = "MainMenu.fxml";
//public static String screen3ID = "screen3";
//public static String screen3File = "Screen3.fxml";
public static Functions databaseConnection;

@Override
public void start(Stage stage) throws Exception {

    databaseConnection = new Functions();
    databaseConnection.DB_Connect();

    octocash.GUI_Screens.ScreensController mainContainer = new octocash.GUI_Screens.ScreensController();
    mainContainer.loadScreen(Main.screen1ID, Main.screen1File);
    mainContainer.loadScreen(Main.screen2ID, Main.screen2File);

    mainContainer.setScreen(Main.screen1ID);

    Group root = new Group(); //als je meerdere vensters in moet laden
    root.getChildren().addAll(mainContainer);
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.setFullScreen(true); //full screen without borders (no program menu bars)
    stage.setFullScreenExitHint(""); //Don't show "Press ESC to exit full screen"
    //stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH); //NIET AANZETTEN VOOR JE IETS ANDERS GEMAAKT HEBT ZODAT JE ERUIT KUNT
    stage.show();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}   
}

LockscreenController.java

public class LockscreenController implements Initializable, ControlledScreen {

ScreensController myController;

@FXML
private PasswordField passwordField;
public FlowPane mainContent;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

@Override
public void initialize(URL url, ResourceBundle rb) {
    mainContent.setPrefSize(screenSize.getWidth(), screenSize.getHeight());
}

public void setScreenParent(ScreensController screenParent){
    myController = screenParent;
}

@FXML
private void goToMainMenu(){
   myController.setScreen(octocash.Main.screen2ID); 
}

public static String employeeName;
public static String employeeIsAdmin;

@FXML
private void checkPassword(ActionEvent event){
   String input = passwordField.getText();
   String needsToBeChecked;
   needsToBeChecked = (new octocash.Functions()).hashPassword(input);
   String[][] employeeInfo = octocash.Main.databaseConnection.getData("some_query", Arrays.asList("naam","isAdmin"));

   if(employeeInfo[0][0] != null) {
       employeeName = employeeInfo[0][0];
       employeeIsAdmin = employeeInfo[0][1];
       goToMainMenu();
       passwordField.setText("");
   }
   else{
       passwordField.setText("");
   } 
}   
}

MainMenuController.java

public class MainMenuController implements Initializable, ControlledScreen {

ScreensController myController;

public FlowPane mainContent;
public ToolBar toolBar;
public Region spacerToolbar;
public HBox buttonHolder;
public Button exitButton;
public Label currentlyLoggedIn;
public Button testButton;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

@Override
public void initialize(URL url, ResourceBundle rb) {
    mainContent.setPrefSize(screenSize.getWidth(), screenSize.getHeight());
    toolBar.setMinWidth(screenSize.getWidth());
    buttonHolder.setHgrow(spacerToolbar, Priority.ALWAYS); //Align buttonHolder to the right
}

public void setScreenParent(ScreensController screenParent){
    myController = screenParent;
}

@FXML
private void exitApplication(){
    Stage stage = (Stage) exitButton.getScene().getWindow();
    stage.close();
} 
}

Now: I want to get the value for employeeName from LockscreenController and send it to MainMenuController, without using the initialize method.

bashoogzaad
  • 4,611
  • 8
  • 40
  • 65
  • Maybe `mainMenuScreenController.setUserLabel(loggedInUserName);` – Uluk Biy Sep 26 '14 at 11:08
  • Do you know how data is transferred between controllers ? – ItachiUchiha Sep 26 '14 at 12:21
  • @UlukBiy it is not only required for the username, but later on also for other string variables. – bashoogzaad Sep 26 '14 at 12:26
  • @ItachiUchiha No, that is exactly what I want to know. – bashoogzaad Sep 26 '14 at 12:27
  • @bashoogzaad please go through [Multiple FXML with Controllers, share object](https://stackoverflow.com/questions/12166786/multiple-fxml-with-controllers-share-object) and [Passing Parameters JavaFX FXML](http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) and if you still have doubt, please reach us – ItachiUchiha Sep 26 '14 at 12:32
  • @ItachiUchiha i have gone through those pages but that doesnt work with my code, because all pages are initialized when the application starts (see code above). How can i do it in my case? – bashoogzaad Sep 26 '14 at 18:28

1 Answers1

1

you have to figure out a way to link the controllers between them , or just the controllers that must have access to other controllers and you have to implement a method like

mainController.refreshMainMenuLabel(User user)

so when a user is logged in, that controller will call the refreshMainMenuLabel of the mainController

EDIT

ill give you an example with 2 controllers

1st define the AppContext

 public static class AppContext{

            //you can add the controllers by their variables 
            private Controller1 test1;
            private Controller2 test2;

            //or from a list which will require handling , but it will be more dynamic
              private List<Controller> controllers;
            private static AppContext context=null;
            //You make the constructor private so its really a sigleton ,
            //cause noone can access it from outer package
            private AppContext()
            {

            }

           public static AppContext getAppContext(){
               if(context==null)
                      context=new AppContext();
               return context;
           }

           public void setController1(Controller1 e)
           {
               test1=e;
           }

           public void setController2(Controller2 e)
           {
               test2=e;
           }

           public Controller1 getController1()
           {
               return test1;
           }

           public Controller2 getController2()
           {
               return test2;
           }  

        }

so those methods can be called like AppContext.getAppContext().getController1() from everywhere in your app cause getAppcontext is static, if you have any problems let me know

AntJavaDev
  • 1,204
  • 1
  • 18
  • 24
  • Thanks for your comment, but I do not know how to link the controllers. I am already aware of the method I might need to implement. – bashoogzaad Sep 26 '14 at 12:27
  • well the simpliest method but not the best is to pass them into the controller's constuctor , or you could make a singleton class from which you set and get the active controllers , and that class will be available for all other classes in your project so you can refer to all controllers at runtime – AntJavaDev Sep 26 '14 at 12:30
  • Could you give an example of how to create such a singleton class, and where to define it? – bashoogzaad Sep 26 '14 at 12:33
  • Thanks for the example! I am now able to set the value of a variable in the AppContext from the first controller, but I can not get it in the second controller, because I can not put it in the initialize method, because it has already been executed. The initialize method is already executed, because all the screens are loaded when the applications starts, and put in a StackPane. I used this: https://www.youtube.com/watch?v=5GsdaZWDcdY – bashoogzaad Sep 26 '14 at 13:15
  • the init method is used to initialize the frame , when the user is logged in , you will NOT initialize again the frame cause its already initialized but you will call the loginUser() method from its controller which will refresh the contents of the ALREADY initialized frame – AntJavaDev Sep 26 '14 at 13:18
  • Where do I have to call the loginUser() in the controller? – bashoogzaad Sep 26 '14 at 13:22
  • at the lockscreen controller , when the user authenticates you validate the user's info , if true then refresh the frame with user if false keep the frames locked – AntJavaDev Sep 26 '14 at 13:54
  • Last question: how to refresh a frame with JavaFX? – bashoogzaad Sep 26 '14 at 14:01
  • refresh a frame means you will call the specified frame's controller's method that suits you , in your case you need at the mainScreenController a method that will refresh its content by the user that is logged on , which will be called from that lockScreenController if the user passed the validation – AntJavaDev Sep 26 '14 at 14:07
  • I have edited my original post, with the code, which enables you to get an overview of the situation. – bashoogzaad Sep 26 '14 at 16:56
  • as i see you havent understand the first post , have you created an appcontext in order to bind the controllers at they start up?? – AntJavaDev Sep 26 '14 at 19:15