Search code examples
javajavafxfxml

Multiple FXML files with controllers for each file - TextArea not displaying text properly after append


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()?


Solution

  • 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);
        }
    }