Q:

JavaFX how to access field (TextArea) from other Stage (Class)

I have one main Scene, where I keep all mu GUI. It has a menu, which opens new scenes, where I have some settings:
public class StartController implements Initializable {

// Some other fields

    @FXML
    private TextArea eventLog;

// This method opens "new project" window

@FXML
    private void openProjectWindow(Event event) throws IOException {

        eventLog.appendText(EventLogUtils.getDate() + STATUS.INFO
                + " New project window opened\n");

        GridPane newProjectWindow = (GridPane) FXMLLoader.load(getClass()
                .getResource("../view/project.fxml"));
        Scene scene = new Scene(newProjectWindow, 800, 600);
        scene.getStylesheets().add(
                getClass().getResource("../view/main.css").toExternalForm());
        Stage projectStage = new Stage();
        projectStage.setScene(scene);
        projectStage.setTitle("New Project");
        projectStage.show();
    } 

}

This eventLog TextArea is a place where I put all the logs, like application started, settings changed, project saved etc. I'm opening new scene with openProjectWindow void and I'm adding this information to my logger. My new window is a separate class:
public class ProjectWindowController implements Initializable {

// fields and methodes to fill and save forms

}

Once It's done I need  to access StartController.eventLog somehow, but nothing I tried is working:

Changing eventLog to public
Extending StartController by ProjectWindowController and trying super.eventLog.appendText()
Changing eventLog to public static (throws exception during runtime)

Is there any way to access this field from different Stage (Class) ? I'd normally use Singleton design pattern, but I think it's impossible in this case. I was looking for similar questions, but I didn't find any case matching my problem. Thanks for any help!

A:

Rather than exposing the UI control to another class and modifying it directly, a better approach (and probably easier to use) would be to use an intermediate class or set of classes to hold all the information you're trying to log, and use property binding to bind the data to the event log text area.
That way, you maintain the boundary of your classes and you keep relevant data organized in the proper location, and you can allow anyone who wants the data to access it in a standard way.
Something like:
public final class LogInfo {
    private static StringProperty logData = new SimpleStringProperty();
    // methods that set/format logData based on changes from your UI

    // provide public access to the property
    public static StringProperty logDataProperty() { return logData; }
    public static void setLogData(String data) { logData.set(data); }
    public static String getLogData() { return logData.get(); }
}

Then in your UI scene, you can bind the textProperty of the UI control to the log data like so:
public class StartController implements Initializable {

// Some other fields

    @FXML
    private TextArea eventLog;

    @FXML
    public void initialize(URL url, ResourceBundle resourceBundle ) {
        // other initialize stuff

        // bind the log property to this event log
        // Bindings.bindBidirectional() if you want to be able to control the property from both sides.
        eventLog.textProperty().bind(LogInfo.logDataProperty());

        // ...
    }
}

You can choose how the UI updates the log info property in your LogInfo class, but this should help you get further while still maintaining information separation.

