0

I would like to know a best practise for a JavaFX application which has many views. I'm using the MVC pattern. On the views it should be possible that the user can add/edit/delete model data of the connected view. Let's assume the scenario with a left side button navigation menu where it's possible to set the center area of a BoraderPane layout (See picture).

Start view of a simple example application

Counter view of a example application (after leaving and coming back to this view the counter value should still be accasable/shown)

When I switch the view and come back to the counter view, then the counter value is not shown anymore. With the solution below, I the FXMLLoader loads the fxml file and also a new controller instance, so the data which were set before are lost. At the moment the counter value is implemented in the controller, but in a later stage (when know a way how to relate the Model with it's controller) I would like to store it in a CounterModel. Ofc this is a simple example, the real application has many views and also more models which need to be organized in the way that the model is connected to the right controller.

The questions would be:

  1. Where is the best location to store view depending data for a view, where the data only belongs to one single particular view and how can I make sure that the model is connected to it's controller again? (Maybe there is also another way where it's not possible to delete the controller instance after leaving the view???)

  2. (is not part of the application above, but related to this topic) what is the best practise to filter a data source (Model) which holds an array of objects to show filtered data on different views?

Here is the code for the above application:

Below Code for MainApplication.java:

public class MainApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("main- 
            view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 300, 100);
        stage.setTitle("Example");
        stage.setScene(scene);
        stage.show();
    }

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

Code for MainController.java:

public class MainController implements Initializable {

    @FXML
    private BorderPane mainPane;

    @FXML
    protected void onSwitchViewButtonClick(ActionEvent event) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("/src/main/resources/com/example/demo/counter-view.fxml"));
        AnchorPane counterViewScene = fxmlLoader.load();
        mainPane.setCenter(counterViewScene);
    }
    @FXML
    void onStartViewButtonClick(ActionEvent event) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("/src/main/resources/com/example/demo/start-view.fxml"));
        AnchorPane counterViewScene = fxmlLoader.load();
        mainPane.setCenter(counterViewScene);
    }
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("/src/main/resources/com/example/demo/start-view.fxml"));
        AnchorPane counterViewScene = null;
        try {
            counterViewScene = fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mainPane.setCenter(counterViewScene);
    }
}

Code for CounterView.java:

public class CounterView {

    private Integer counter=0;
    @FXML
    private Label labelCounterValue;

    @FXML
    void onIncrementButtonClick(ActionEvent event) {
        counter++;
        labelCounterValue.setText(counter.toString());
    }
}
Felix D
  • 3
  • 2
  • BTW: your resource lookup is wrong, see its java doc or f.i. https://stackoverflow.com/questions/61531317/how-do-i-determine-the-correct-path-for-fxml-files-css-files-images-and-other to learn how to do it correctly – kleopatra Nov 26 '21 at 09:38
  • 2
    The most important thing which you have to learn is that the FXML controller is NOT part of the model. It is a part of the view. Some people call it the "code behind". So the controller should never hold any model data itself. It should always fetch it from the model when needed. This would then solve your current problem. – mipa Nov 26 '21 at 11:19
  • I highly recommend you read eden codings [mvc in JavaFX tutorial](https://edencoding.com/mvc-in-javafx/), it provides an example strategy for implementing mipa’s suggestion. Optionally, you could study other eden coding guides like [linking the controller to your app](https://edencoding.com/how-to-connect-your-controller-with-your-app-javafx/) and [dependency injection](https://edencoding.com/dependency-injection/). – jewelsea Nov 26 '21 at 21:47

0 Answers0