2 Replies Latest reply: Mar 22, 2013 4:43 PM by drenda81 RSS

    Best practice to create views

    drenda81
      Hi,
      I've a question about best practice to develop a large application with many complex views.
      Typically at each time only one views is displayed. User can go from a view to another using a menu bar.
      Every view is build with fxml, so my question is about how to create views and how switch from one to another.

      Actually I load fxml every time the view is required:
      FXMLLoader loader = new FXMLLoader();
      InputStream in = MyController.class.getResourceAsStream("MyView.fxml");
      loader.setBuilderFactory(new JavaFXBuilderFactory());
      loader.setLocation(OptixController.class.getResource("MyView.fxml"));
      BorderPane page;
      try {
           page = (BorderPane) loader.load(in);
           } finally {
                if (in != null) {
                     in.close();
                }
          }
      // appController = loader.getController();
      Scene scene = new Scene(page, MINIMUM_WINDOW_WIDTH, MINIMUM_WINDOW_HEIGHT);
      scene.getStylesheets().add("it/myapp/Mycss.css");
      stage.setScene(scene);
      stage.sizeToScene();
      stage.setScene(scene);
      stage.sizeToScene();
      stage.centerOnScreen();
      stage.show();
      My questions:
      1- is a good practice reload every time the fxml to design the view?
      2- is a good practice create every time a new Scene or to have an unique scene in the app and every time clear all elements in it and set the new view?
      3- the views should be keep in memory to avoid performace issue or it is a mistake? I think that every time a view should be destroy in order to free memory.


      Thanks very much

      Edited by: drenda81 on 21-mar-2013 10.41
        • 1. Re: Best practice to create views
          James_D
          >

          >
          My questions:
          1- is a good practice reload every time the fxml to design the view?
          2- is a good practice create every time a new Scene or to have an unique scene in the app and every time clear all elements in it and set the new view?
          3- the views should be keep in memory to avoid performace issue or it is a mistake? I think that every time a view should be destroy in order to free memory.
          In choosing between 1 and 3 above, I think either is fine. Loading the FXML on demand every time will be slightly slower, but assuming you are not doing something unusual such as loading over a network connection it won't be noticeable to the user. Loading all views at startup and keeping them in memory uses more memory, but again, it's unlikely to be an issue. I would choose whichever is easier to code (probably loading on demand).

          In choosing between reusing a Scene or creating a new one each time, I would reuse the Scene. "Clearing all elements in it" only needs you to call scene.setRoot(...) and pass in the new view. Since the Scene has a mutable root property, you may as well make use of it and save the (small) overhead of instantiating a new Scene each time. You might consider exposing a currentView property somewhere (say, in your main controller, or model if you have a separate model class) and binding the Scene's root property to it. Something like:
          public class MainController {
            private final ObjectProperty<Parent> currentView ;
          
            public MainController() {
              currentView = new SimpleObjectProperty<Parent>(this, "currentView");
            }
          
            public void initialize() {
              ...
              currentView.set(loadView("StartView.fxml"));
            }
          
            public ObjectProperty<Parent> currentViewProperty() {
              return currentView ;
            }
          
            // event handler to load View1:
            @FXML
            private void loadView1() {
              currentView.set(loadView("View1.fxml"));
            }
          
            // similarly for other views...
          
            private Parent loadView(String fxmlFile) {
              try {
               Parent view = FXMLLoader.load(getClass().getResource(fxmlFile));
               return view ;
              } catch (...) { ... }
            }
          }
          Then your application can do this:
          @Override
          public void start(Stage primaryStage) {
             Scene scene = new Scene();
             FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
             MainController controller = (MainController) loader.getController();
             scene.rootProperty().bind(controller.currentViewProperty());
             // set scene in stage, etc...
          }
          This means your Controller doesn't need to know about the Scene, which maintains a nice decoupling.
          • 2. Re: Best practice to create views
            drenda81
            Thanks very much James. You reply is very useful to me!