0

all the questions I found around here answered how to send data from one controller to another. However, I don't know how to return another value from the second controller to the first one. Basically, send data back and forth while the first controller is still opened.

Main class:

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("Screen1.fxml"));
            Scene scene = new Scene(loader.load());
            primaryStage.setScene(scene);
            primaryStage.setTitle("Screen 1");
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Screen 1 controller:

public class Screen1Controller {
    @FXML
    TextField textFieldScreen1;
    @FXML
    Button buttonScreen1;
    @FXML
    Label labelScreen1;

    @FXML
    private void initialize() {

        buttonScreen1.setOnAction((event) -> {
            try{
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(getClass().getResource("Screen2.fxml"));
                Scene scene = new Scene(loader.load());
                Stage stage = new Stage();

                //Send data to Screen 2
                Screen2Controller controller2 = loader.getController();
                controller2.receiveTextFromScreen1(textFieldScreen1.getText());

                stage.setTitle("Screen 2");
                stage.setScene(scene);
                stage.show();
            }   catch (IOException e) {
                    e.printStackTrace();
                }
        });

    }
}

Screen 2 controller:

public class Screen2Controller {
    @FXML
    TextField textFieldScreen2;
    @FXML
    Button buttonScreen2;
    @FXML
    Label labelScreen2;

    @FXML
    private void initialize() {

        buttonScreen2.setOnAction((event) -> {
            Stage currentStage = (Stage) buttonScreen2.getScene().getWindow();
            currentStage.close();
        });
    }

    public void receiveTextFromScreen1(String stringScreen1){
        labelScreen2.setText(stringScreen1);
    }
}

I have tried to use the same strategy (create a method in Screen1Controller and instantiate Screen1Controller in the second controller) with the following code but it didn't work.

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("Screen2.fxml"));
//Send data to Screen 1
Screen1Controller controller1 = loader.getController();
controller1.receiveTextFromScreen2(textFieldScreen2.getText());

Also, related to this matter (I'm assuming) a second question: how would I update the second view while I change the TextField in controller 1 without creating a new window everytime I click the button (i.e using the same second view instance)?

Any help will be greatly appreciated!

ihavenoidea
  • 629
  • 1
  • 7
  • 26
  • See https://stackoverflow.com/questions/36482632/javafx-using-objects-from-maincontroller-or-other-controllers-in-proper-controll. Basically you have to pass a reference to the first controller to the second controller. That way the second controller can call methods on the first controller. You should consider using a MVC approach instead of wiring all the controllers together like this. – James_D Jan 05 '18 at 00:59
  • Hi, the controllers are in different classes! Can you give more details in how I should pass this reference? Thank you. – ihavenoidea Jan 05 '18 at 02:49
  • Of course the controllers are from different classes. What's wrong with the link I posted? – James_D Jan 05 '18 at 02:57

1 Answers1

0

Create a constructor

public Screen1Controller {
Arrow the parameters
}

and when you call the controller, you parse the parameter:

void on2players(ActionEvent event) throws IOException {
    client.out.println("ACTION NEWGAME 2 4");
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/boardscreen.fxml"));
    loader.setController(new Screen1Controller(parameter);
    Parent root = loader.load();
    Scene scene= new Scene(root);
    Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow();
    window.setScene(scene);
    window.show();
}


public class Screen1Controller implements Initializable {

    public Screen1Controller() {
        //parameters
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    switch(numberOfPlayers){
    case 2:
    //TODO...creating board for 2 players
    case 3:
    //TODO creatinf board for 3 players
   }

    }

If you do this, you force the fxml loader to call the controller. NOTE: You should get the controller inside .FXML