Search code examples
javadesign-patternsjavafxfxmlcontrollers

JavaFX, FXML and controllers: switching scenes, maintaining scene data


Hello programmers and architects!
I'm new here and... I think my english could be... terrible! :-D So... be careful with me... please.

I have an architectural question about JavaFX, FXML and the various methods to switch scenes, mantaining data among all scenes... I have used a personal solution and I need to know if it's an acceptabile solution or not (at the architectural level).

I'll try to explain my solution.
I have used a sort of "inverse" of Observer Pattern: instead use many observers for each observable, I've used one observer (a specific Class) and many observables (all controllers).
So, when it's time to change scene, the Controller of the current scene notifies to Observer to do that. Observer removes old scene and loads the new one.

Some details.
I have created a class named SceneObserver that implements java.util.Observer.
enter image description here
I use SceneObserver in order to:

  • register SceneObserver as observer of all my controllers
  • load a specifc FXML file
  • create a new Scene with only an AnchorPanel as root element ad use the root.getChildren().add() method to append to the root element the loaded FXML
  • set a specific controller for the FXMLLoader (I have NOT used "fx:controller" inside the various FXML.)

All my Controllers extend java.util.Observable (this is an example).
enter image description here
When a certain type of situation happens in a scene and it's necessary to switch scene, the scene notifies to SceneObserver the change (Observer Pattern), SceneObserver destroys the old scene and loads the new one. In other words I'm using only one observer to observe all controllers (the inverse of the Observe Pattern).
All works, but I know that this is not enough!

So, the question is: speaking at the architectural level, is this one an acceptabile solution?

I know, this is not the only one and surely there are others better ways, but... what about this one?

Why have I used this solution?
Well, two reasons:

  1. load only necessary FXML (more rapid application)
  2. leave controllers decoupled

Thanks to all and... sorry for my english :-(


Solution

  • Well...

    after that I've read and tested different solutions, that I recommend to read:

    https://web.archive.org/web/20160316234709/
    https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1
    https://github.com/google/guava/wiki/EventBusExplained
    http://eventbus.org/

    I've decided to realize my own solution, using a more simple approach: a Router Pattern.

    My goal was to decouple the various controllers in my JavaFX application, leaving possibility to communicate among their.
    Instead to use event handler, parameters or obsolete event-bus, it seems that a simple Router Pattern can solve the issue. Every controller must know the Router (obviously a singleton) and Router must know every controllers. In this way I have simply trasformed a many-to-many class relation to one-to-many without nothing of "too magic" and I can send every kind of messages among controllers. In the small:
    In the Router I declare one property for each controller and a set method in order to link exactly that instance of controller, like this:

    public class Router {
        private MainCtrl mainCtrl;
        ...
        protected void setMainCtrl(MainCtrl mainCtrl) {
            this.mainCtrl = mainCtrl;
        }
    }
    

    Then, in each controller I declare a Router object (router) and in the initialize() method of each controller I write this (router must be a singleton!):

    public void initialize() {
        router.setMainCtrl(this);
        ...
    }
    

    That's all.