0

I want to divide my FXML into smaller files, each having its own controller. In main I create instance for each controller and get access to textAreaSample and trying to append text. I don't see text is changing. Why? Alert is displaying text from this TextArea:

alert.setContentText(textAreaSample.getText());

I don't know how to set all fxml files and controllers. How should I set all of this?

Here is my main `sample.fxml' file:

<GridPane fx:controller="sample.ControllerSample"
      xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">

    <fx:include fx:id="sending" source="Sending.fxml" GridPane.columnIndex="0" GridPane.rowIndex="0"/>

    <TextArea fx:id="textAreaSample" prefWidth="200" prefHeight="200"
          GridPane.columnIndex="1" GridPane.rowIndex="0" text="Sample">
    </TextArea>
</GridPane>

and its controller:

public class ControllerSample {

    @FXML
    private TextArea textAreaSample;

    public ControllerSample() {}

    public TextArea getTextAreaSample() {
        return textAreaSample;
    }

    public void setTextAreaSample(TextArea textAreaSample) {
        this.textAreaSample = textAreaSample;
    }
}

Now I have Sending.fxml file:

<GridPane fx:controller="sample.ControllerSending"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">

        <fx:include fx:id="sendingPhotos" source="SendingPhotos.fxml" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
</GridPane>

and its controller:

public class ControllerSending {

    public ControllerSending() {}
}

Here is SendingPhotos.fxml code:

<TextArea xmlns="http://javafx.com/javafx"
      xmlns:fx="http://javafx.com/fxml"
      fx:controller="sample.ControllerSendingPhotos" fx:id="textAreaSendingPhotos" prefWidth="200" prefHeight="200"
      text="Photos"/>

and controller:

public class ControllerSendingPhotos {

    @FXML
    private TextArea textAreaSendingPhotos;

    public ControllerSendingPhotos() {}

    public TextArea getTextAreaSendingPhotos() {
        return textAreaSendingPhotos;
    }

    public void setTextAreaSendingPhotos(TextArea textAreaSendingPhotos) {
        this.textAreaSendingPhotos = textAreaSendingPhotos;
    }
}

Now Main.java code:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        FXMLLoader loaderSample = new FXMLLoader(getClass().getResource("sample.fxml"));
        FXMLLoader loaderSending = new FXMLLoader(getClass().getResource("Sending.fxml"));
        FXMLLoader loaderSendingPhotos = new FXMLLoader(getClass().getResource("SendingPhotos.fxml"));

        loaderSample.load();
        loaderSending.load();
        loaderSendingPhotos.load();

        ControllerSample controllerSample = (ControllerSample) loaderSample.getController();
        ControllerSending controllerSending = (ControllerSending) loaderSending.getController();
        ControllerSendingPhotos controllerSendingPhotos = (ControllerSendingPhotos) loaderSendingPhotos.getController();

        TextArea textAreaSample = controllerSample.getTextAreaSample();
        textAreaSample.setText("\ndebug textAreaSample\n");

        Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "");

        alert.setContentText(textAreaSample.getText());
        alert.showAndWait();

        //TextArea textAreaSendingPhotos = controllerSendingPhotos.getTextAreaSendingPhotos();
        //textAreaSendingPhotos.appendText("\ndebug textAreaSendingPhotos\n");

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 800, 400));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Edit: I define ControllerSending in ControllerSample with getters and setters? And then in ControllerSending I define ControllerSendingPhoto with getters and setters? And then in Main to declare ControllerSendingPhotos I use controllerSample.getControllerSending().getControllerSendingPhotos()?

Urle
  • 131
  • 10
  • Maybe https://stackoverflow.com/questions/12543487/javafx-nested-controllers-fxml-include helps? – Ralf Renz Feb 25 '19 at 10:51
  • The point is I don't get any error, nothing is null, even (after checking with alert) `textArea` contains appended text. It is only not displaying in `TextArea`. – Urle Feb 25 '19 at 11:02
  • If you have nested FXMLs you should not load them separately. The inner FXMLs are automatically loaded with the outer one. It's possible that the textArea exists twice. One is displayed and the other one is the one you check in your code. – Ralf Renz Feb 25 '19 at 11:40
  • I also thought that there can be more textAreas. But this `textAreaSample` is placed in main FXML file. So, first I started testing with this one. – Urle Feb 25 '19 at 11:45
  • 1
    Grrr. You load the sample.fxml twice. The second time is direct before the primaryStage.setTitle. That destroys what you made before. – Ralf Renz Feb 25 '19 at 12:16

1 Answers1

2

To access the textArea in the nested fxml you have to change the Controllers:

public class ControllerSample {
    @FXML
    private TextArea textAreaSample;

    @FXML
    private ControllerSending sendingController;

    public ControllerSample() {
    }

    public TextArea getTextAreaSample() {
        return textAreaSample;
    }

    public void setTextAreaSample(TextArea textAreaSample) {
        this.textAreaSample = textAreaSample;
    }

    protected ControllerSending getSendingController() {
        return sendingController;
    }
}

public class ControllerSending {
    @FXML
    private ControllerSendingPhotos sendingPhotosController;

    public ControllerSending() {
    }

    protected ControllerSendingPhotos getSendingPhotosController() {
        return sendingPhotosController;
    }
}

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        FXMLLoader loaderSample = new FXMLLoader(getClass().getResource("sample.fxml"));

        Parent root = loaderSample.load();

        ControllerSample controllerSample = (ControllerSample) loaderSample.getController();

        TextArea textAreaSample = controllerSample.getTextAreaSample();
        textAreaSample.setText("\ndebug textAreaSample\n");

        TextArea textAreaSendingPhotos = controllerSample.getSendingController().getSendingPhotosController()
            .getTextAreaSendingPhotos();
        textAreaSendingPhotos.setText("test test test");

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 800, 400));
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}
Pochmurnik
  • 780
  • 6
  • 18
  • 35
Ralf Renz
  • 1,061
  • 5
  • 7
  • Is there any difference between `sendingController` and `controllerSending` name? – Urle Feb 26 '19 at 07:21
  • There is... `controllerSending` looks better for me, but I get Null Pointer Exception. I see nowhere in my project `sendingController` name, is this any naming convention? – Urle Feb 26 '19 at 07:41
  • I see, I refactored `fx:id` in my `sending.fxml` to `sendingG` and in ControllerSample.java appeared `sendingGController`. – Urle Feb 26 '19 at 07:45