0

I have a multi scene JavaFX FXML application based on Angela Caicedo code https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1

I have added a TextField to Scene2.fxml and Scene3.fxml files each scene has its own Controller Class with a ScreensController class that loads a HashMap with Id name, Node screen that is defined in the ScreensFramework class (Main class)

public void addScreen(String name, Node screen) {
    screens.put(name, screen);
}

So each time you click a Button on a screen (scene) you fire an ActionEvent and move to another screen

myController.setScreen(ScreensFramework.screen2ID);

What I would like to do if it is possible is use the value in the TextField on Screen2 and transfer it to the TextField on Scene3. I have discovered that unless both FXML files are loaded this is so far not possible. This is a desktop application. So how do you create a variable that is GLOBAL and has a life after one class is unloaded or one FXML file is unloaded? At this point I do not want a database to accomplish this task. I have developed in Visual Basic 6 where I would just declare a global variable that could be used through out the application.

James_D
  • 201,275
  • 16
  • 291
  • 322
Vector
  • 3,066
  • 5
  • 27
  • 54
  • Read http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml/14190310#14190310 and see if it helps. – James_D Mar 31 '15 at 22:27
  • @James_D thanks but all the links on this topic seem to act as if the variable is predefined and not entered at run time here is a link that works http://stackoverflow.com/questions/12166786/multiple-fxml-with-controllers-share-object/ but the variable is pre defined – Vector Apr 01 '15 at 00:28
  • Create a model class (just something to hold the data). You can define that first and pass it to any controller you need. Then just modify it's state from one controller and the other(s) will have access to the state. – James_D Apr 01 '15 at 00:31
  • Actually, can't you just put the data you need in the `ScreensController` class? All the controllers have a reference to a single instance of that, so any data you put there is shared by all the controllers. – James_D Apr 01 '15 at 01:31
  • @James_D I will post the code here as this site in not even friendly for posting code. My question is where or how do I capture data entered on Screen 4 and transfer it to Screen 3 I do need to make a trip back to the ScreensController so where in that class would I address that variable and hand it off to the correct controller in this case Screen3 https://community.oracle.com/message/12985002#12985002 – Vector Apr 02 '15 at 03:17
  • Please post relevant code in the question instead of linking it. Just paste it in, select it, and press the "code" button (`{ }`) at the top of the edit pane. – James_D Apr 02 '15 at 11:56

1 Answers1

0

Define a model class:

public class Model {

    // Define properties, for example:

    private StringProperty text = new SimpleStringProperty();

    public StringProperty textProperty() {
        return text ;
    }

    public final String getText() {
        return textProperty().get();
    }

    public final void setText(String text) {
        textProperty().set(text);
    }

    // other properties...

}

Instantiate it in your ScreensController class and expose it:

public class ScreensController extends StackPane {

    private final Model model = new Model() ;

    public Model getModel() {
        return model ;
    }

    // other code as before...
}

Now you can just bind things together:

public class ScreenController2 implements ControlledScreen, Initializable {

    private ScreensController myController ;

    @FXML
    private TextField textField ;

    // other code...

    @Override 
    public void setScreenParent(ScreensController parent) {
        this.myController = parent ;

        // Either:
        myController.getModel().setText(textField.getText());
        textField.textProperty().addListener((obs, oldText, newText) -> 
            myController.getModel().setText(newText));

        // or, depending on the exact behavior you want:
        myController.getModel().textProperty()
            .bindBidirectional(textField.textProperty());
    }

    // ...
}

and

public class ScreenController3 implements ControlledScreen, Initializable {

    private ScreensController myController ;

    @FXML
    private TextField textField ;

    // other code ...

    @Override
    public void setScreenParent(ScreensController parent) {
        this.myController = parent ;

        // Again, replace the next two lines with a bidirectional
        // binding if that is the behavior you want
        textField.setText(myController.getModel().getText());
        myController.getModel().textProperty().addListener((obs, oldText, newText) -> 
            textField.setText(newText));
    }

    // ...
}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Note that this really works exactly the same way as http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml/14190310#14190310, but adapted for Angela Caicedo's framework. In your comment you said the "variables were predefined": That's no problem; the `model` can be predefined, you just update its state as and when you need. – James_D Apr 02 '15 at 16:19
  • @Jame_D Thank You very helpful I am still working on how it all works but the code is working. I have written the application with one FXML file and one Controller with 6 scenes by making the AnchorPane 400 by 300 and setting a Pane to 1200 by 900 so each view is the size of the AnchorPane I need to make a new post on how to manage a ComboBox in an FX app with FXML thanks dwight – Vector Apr 08 '15 at 20:47