-3

I have 2 Controllers and I want to pass values from second controller to first controller, here are code sample:

    FXMLController.java
        private int paramAnswers;
        private int paramNotificationTime;
        private int paramNotificationDelay;

            @FXML
            private void handleMenuItemOptionsAction(ActionEvent event) throws IOException{
                Parent root = FXMLLoader.load(getClass().getResource("/fxml/Options.fxml")); // UNDECORATED*

                Scene scene = new Scene(root, Color.TRANSPARENT);
                final Stage stage = new Stage();
                stage.setTitle("Options");
                stage.setScene(scene);  
                stage.show();
        }

public void setOptionsParams(int paramAnswers, int paramNotificationTime, int paramNotificationDelay){
        this.paramAnswers = paramAnswers;
        this.paramNotificationTime = paramNotificationTime;
        this.paramNotificationDelay = paramNotificationDelay;
    }

and second controller:

    OptionsController.java
    private FXMLController parentController;
    private int paramAnswers;
        private int paramNotificationTime;
        private int paramNotificationDelay;

    @Override
        public void initialize(URL location, ResourceBundle resources) { 
    .... }

    @FXML
        private void handleButtonSaveAction(ActionEvent event) throws IOException{
            /*Pass these parameteres OptionsController parameters back to the FXMLController like parentController.setOptionsParams(paramAnswers, paramNotificationTime, paramNotificationDelay);
*/
(((Button)event.getSource()).getScene().getWindow())).close();

        } 

Arleady tried with parsing FXMLControler as .this into OptionsController initialize method, tried making listers and bunch of other resolved problems on stackoverflow but it just don't want work :< I need to pass that atributes back to FXMLController and close child window, so my main app would change behavior depending on passed values... :X For any help I will be grateful

2 Answers2

1

you can have a function in the second controller let's say passParams() set it's parameters what every you want to pass to that controller and from the first controller when you click on a button or something
this line

FXMLLoader.load(getClass().getResource("/fxml/Options.fxml"));

need to be changed to

FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Options.fxml"));
Parent root = (Parent) loader.load();
OptionsController controller = loader.getController();

EDIT you need to pass the first controller to the second controller

controller.setParentController(this); // this is the first controller

in Second controller

FirstController mController;
public void setParams(FirstController controller) {
    this.mController = controller;
}

now in the button click function you use the mController you got from the previous step

mController.setOptionsParams(...); //send the params collected from the textfields

this function is implemented in the FirstController
Note: a more general way to do this by using call-backs it's the same but your code depends on interfaces not concrete classes by implementing a general interface in FirstController that have the setOptionParams() method

Ahmed Emad
  • 674
  • 6
  • 19
  • that's not exacly what I need to achieve. In OptionsController i have sliders and so on, and after i put new arguments via Options UI i press the button Accept and that button should pass all new values into first FXMLController. Thats why controller.passParams(...) as you said in answer wont work, becouse it have to be initialized by button in OptionsController :( – Damian Szarik Paul Aug 24 '18 at 09:24
  • you can pass the controller as a parameter in that function so you can call back but for make sure that first controller is not null as after you go to another screen the controller get garbage collected if you don't have reference to it – Ahmed Emad Aug 24 '18 at 10:15
  • wherever i pass controller i still get nullpointerexception ;v where should i pass it (or how should i pass it? should i make function in new controller and in that function put your code: FXMOLlloader loader.... and in first controller make object of second controller, then secondController.initialize()?) it really starting pissing me off :( – Damian Szarik Paul Aug 24 '18 at 13:16
  • don't worry we will do it first you want to pass something from SecondController to FirstController when you hit button on SecondScreen is that right ? – Ahmed Emad Aug 24 '18 at 13:29
  • yes, thats right.. I have onButtonClickAction in second controller which gets arguments from Textboxes and it should send these arguments into variables in first controller and close second window after – Damian Szarik Paul Aug 24 '18 at 14:07
  • SecondController button method: @FXML private void handleButtonSaveAction(ActionEvent event) throws IOException{ paramAnswers = Integer.parseInt(field.getText()); paramNotificationTime = Integer.parseInt(field1.getText()); paramNotificationDelay = Integer.parseInt(field2.getText()); // Here need to pass these values to first Controller //((Stage)(((Button)event.getSource()).getScene().getWindow())).close(); } – Damian Szarik Paul Aug 24 '18 at 14:12
  • See my edited answer and feel free to ask if nothing is not clear – Ahmed Emad Aug 24 '18 at 14:35
  • works like a charm now... i just couldnt manage where exacly put it *sigh*, thank you for guiding noob like me :)) – Damian Szarik Paul Aug 24 '18 at 14:47
  • You are welcome try the callback option it's the best practice :D – Ahmed Emad Aug 24 '18 at 14:50
-1

First you add a callback interface to your parent controller class:

public interface OptionCallback {
     public void setOptionsParams(int paramAnswers, int paramNotificationTime, int paramNotificationDelay);
 }

 public class YourParentController implements Initializable, OptionCallback {
   ...
 }    

Using the FXMLLoader object you can get a hold of your child controller object and pass the parent object to it:

FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("yourFXML.fxml"));

Parent root = (Parent) loader.load();

YourChildController yourChildController = loader.<YourChildController>getController();

yourChildConrtoller.registerCallback(this);

In the childController you save that callback:

private OptionCallback optionCallback;

public void registerCallback(OptionCallback callback) {
    optionCallback = callback;
}

And whenever results are ready you use it to pass it to parent:

optionCallback.setOptionsParams(...);
Georg
  • 261
  • 1
  • 9