1

I have a FXML file with all the elements like Buttons, Labels, TextFields etc. For the FXML-file I have a controller class, where I can set the text of Labels and so on.

Now I have an extern class, where I need to change the Buttons, Labels etc. too. The problem is, I can't set the elements to static. So how can I change them in a different class?

I already know that there are similiar questions here, but nothing what really helped me. I would really appreciate your help.

Example

FXML

<AnchorPane fx:id="root" prefHeight="1000" prefWidth="1000"
    xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1"
    fx:controller="Controller">
    <Label fx:id="testLabel" layoutX="150" layoutY="200" text=""/>

Controller.java

@FXML private Label testLabel;

AnotherClass.java

testLabel.setText("This is a test");

Main.java

Main.primaryStage = primaryStage;
primaryStage.setTitle("Test Scene");
AnchorPane pane = FXMLLoader.load(Resource.onClassPath("MyScene.fxml").getURL());
Scene scene = new Scene(pane);
primaryStage.setScene(scene);

If I am in the Scene "MyScene.fxml" and click a Button to navigate to the next Scene

@FXML AnchorPane root;
    AnchorPane pane = FXMLLoader.load(Resource.onClassPath("Example.fxml").getURL());
    root.getChildren().setAll(pane);

Now the "Example" Scene has a Controller. I need to get access to the Elements of the Controller from a third Class.. :)

Zauvue
  • 15
  • 5
  • You can simply pass those elements from your controller class to another class via constructor or setter method. There is no need to declare elements as static. – Umer Farooq Apr 29 '18 at 10:19
  • If you want to access ALL 40 elements of controller class then you can declare all elements as `public` and then pass reference of controller class to another class. In this case you dont have to write 40 setters methods – Umer Farooq Apr 29 '18 at 10:28
  • IDEs like Eclipse or IntelliJ have the possibility to generate the getters and setters for you. It is also best practice in Java to use getters and setters rather than making fields public. – vatbub Apr 29 '18 at 10:32
  • @Zauvue How do you instantiate your secondary class? – vatbub Apr 29 '18 at 10:35
  • Please read [this](https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html) or Google Java class instance, then you'll understand – vatbub Apr 29 '18 at 11:15
  • You're using the `fx:controller` attribute wrong: The value of the attribute should contain the fully qualified class name of the controller class, not the file name of the `.java` file containing it's source code. In this case it should be `fx:controller="mypackage.Controller"` or, if the controller is part of the default package `fx:controller="Controller"`. (Does not solve your problem but at least the fxml would load.) BTW: what's wrong with the solutions presented here: https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml ??? – fabian Apr 29 '18 at 12:00
  • Do you create the scene for editing from `Controller` or is created in some different place? – fabian Apr 29 '18 at 12:21
  • It would be good if you post some more code. It is difficult for us to get the point you are mentioning in your comments – Umer Farooq Apr 29 '18 at 12:48
  • Outside your controller class your code should not be aware of the user interface. Doing so will lead to fragile and difficult to maintain software. You should create a model of your domain and let the controller bind the properties of those objects to user interface elements. – M. le Rutte Apr 29 '18 at 13:05
  • It is a common pattern to separate the representation of data to the representation of the user interface. The controller class knows both and updates the user interface in response to model changes and vice versa. In JavaFX this is done using property binding. – M. le Rutte Apr 29 '18 at 13:28

2 Answers2

0

Instead of having the FXMLoader having to construct your controller class you can pass the controller object to an instance of FXMLLoader. This allows you to pass the controller instance to other object, who then can call methods to the controller to do whatever they need.

  Controller controller = ....;
  FXMLLoader loader = new FXMLLoader(Resource.onClassPath("MyScene.fxml").getURL());
  loader.setController(controller);
  AnchorPane pane = loader.load();

  controller.setTestLabel("This is a test.");

However, I would advise to create a domain model and pass that domain model to your controller instance and have it bind user interface elements to domain model elements.

M. le Rutte
  • 3,525
  • 3
  • 18
  • 31
0

Suppose you have MySceneController for MyScene.fxml and ExampleController for Example.fxml

When some button is clicked in MyScene you can access ExampleController like this

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

    AnchorPane pane = loader.load();
    ExampleController exampleController = loader.getController();

    exampleController.getLabel().setText("hello"); // if you have corresponding getters for element

    // or if element is public
    exampleController.label.setText("hello");

    // similary you can pass exampleController to other class and access its element in the other class (as you asked in question)
    new OtherClass(exampleController);

    root.getChildren().setAll(pane);
Umer Farooq
  • 762
  • 1
  • 8
  • 17