How to pass object created in FXML Controller1 to Controller2 of inner FXML control
Asked Answered
C

2

15

I have a JavaFX 2.0 application, which consists of two FXML files, and two controllers for them + one "main" .java file.

At the start time, FXML1 is initialized, like this:

public void start(Stage stage) throws Exception {
    stage.setTitle("Demo Jabber JavaFX Chat");
    
    Parent root = FXMLLoader.load(getClass().getResource("fxml_example.fxml"),
        ResourceBundle.getBundle("fxmlexample.fxml_example"));        
    Scene scene = new Scene(root, 226, 264);
    stage.setScene(scene);
    scene.getStylesheets().add("fxmlexample/fxmlstylesheet.css");
    stage.show();
}

Then, when a button from scene1 is clicked, in its event handler in Controller1 class, I change scene1 root, to show new gui-view for a user. And in this controller I initialize some object. For example, like this:

public class FXMLExampleController {
   //some fields...
   private MySuperObject c;
   @FXML protected void handleSubmitButtonAction(ActionEvent event) {
    //some fields...
    c = new MySuperObject(); //here i initialize my object, i'm interested in
    try {
        c.login(username, password); // some actions with this object, which i need to make.
        Scene cc = buttonStatusText.getScene();
        Parent root = null;
        try {
            //changing a scene content...
            root = FXMLLoader.load(getClass().getResource("fxml_example2.fxml"),
            ResourceBundle.getBundle("fxmlexample.fxml_example"));
        } catch (IOException ex) {
            Logger.getLogger(FXMLExampleController.class.getName()).log(Level.SEVERE, null, ex);
        }
        cc.setRoot(root);
      }

And, after that, I have to do some work with that object on the next scene, and it must be NOT a new instance of the same class, but the object which I have initialized on the first one scene.

I understand how to make these all using "standard java", but I'm kind of confused on this task using JavaFX + FXML.

Counterinsurgency answered 15/3, 2012 at 10:27 Comment(0)
P
27

In FX 2.2 new API for controller-node was introduced:

// create class which is both controller and node
public class InnerFxmlControl extends HBox implements Initializable {
  @FXML public ComboBox cb;

  public InnerFxmlControl () {
     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml_example2.fxml"));
     fxmlLoader.setRoot(this);
     fxmlLoader.setController(this);
     try {
         fxmlLoader.load();            
     } catch (IOException exception) {
         throw new RuntimeException(exception);
     }
  }

with next fxml (note tag fx:root):

<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml">
  <children>
    <ComboBox fx:id="cb" />
  </children>
</fx:root>

By this you've created a new control, which you can use as regular JavaFX controls. E.g. in your case:

@FXML protected void handleSubmitButtonAction(ActionEvent event) {
    // you just create new control, all fxml tricks are encapsulated
    InnerFxmlControl root = new InnerFxmlControl();
    // and you can access all its' methods and fields including matched by @FXML tag:
    root.cb.getItems().add("new item");

    Scene cc = buttonStatusText.getScene();
    cc.setRoot(root);
  }

and in fxml:

<InnerFxmlControl />
Puritanism answered 23/5, 2012 at 11:6 Comment(2)
What are the root.cb. minutes .getItems().add("new item"); and cc .setRoot(root); in last code piece?Shot
Sorry, minutes are from wrong copy-paste. And cc from original Victoria's code sample. Updated.Puritanism
S
3

i'm using 1.7.0_21, it can now code like this: in main app fxml file ,

<VBox ...>
      <fx:include fx:id="tom" source="Tom.fxml" />
</VBox>

and the included fxml can defind it's own fxml file , like this :

<AnchorPane id="AnchorPane" fx:id="tomPan" ... xmlns:fx="http://javafx.com/fxml" fx:controller="**com.tom.fx.TomController**">

and then , in the main application contoller require the "Tom.fxml" 's controller like this :

 @FXML private TomController tomController;

notice the "@FXML" . maybe it invoke the contoller automatic.

Spireme answered 15/6, 2013 at 21:50 Comment(3)
Thanks for contributing! One question: the fx:id is tom but the injected controller is named tomController? By what mechanism are they associated?Flickertail
JavaFX inject "Controller" to fx:id.Mi
In case it was unclear, javaFX will automatically inject the controller into field named <id>Controller. So if the fx:id="tom" it will inject an instance of the controller into a field called tomController.Stunner

© 2022 - 2024 — McMap. All rights reserved.