Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

fxml

javafx-2

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.

like image 704
Victoria Agafonova Avatar asked Mar 15 '12 10:03

Victoria Agafonova


People also ask

Can two FXML files have the same controller?

It's possible to use the same controller class for multiple FXML files, but your code will be really hard to follow, and it's a very bad idea. (Also note that using the fx:controller attribute, you will have a different controller instance each time you call FXMLLoader.

How do I add FXML to another FXML?

The <fx:include> tag can be used to include one fxml file into another. The controller of the included fxml can be injected into the controller of the including file just as any other object created by the FXMLLoader . This is done by adding the fx:id attribute to the <fx:include> element.

How do I specify a controller in FXML?

FXML Controller Classes There are two ways to set a controller for an FXML file. The first way to set a controller is to specify it inside the FXML file. The second way is to set an instance of the controller class on the FXMLLoader instance used to load the FXML document.

Where do FXML files go?

fxml file is located in the src/main/resources folder and my controller is in the src/main/java folder. How do i go about doing this? My src/main/resources folder is in the build path and i am able to call a . properties file that is in the src/main/resources folder from a class in the src/main/java folder.


2 Answers

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 />
like image 174
Sergey Grinev Avatar answered Oct 31 '22 03:10

Sergey Grinev


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.

like image 33
Tom Avatar answered Oct 31 '22 03:10

Tom