简体   繁体   中英

JavaFX Using Stage on ViewModel

I need to know when my application is closing. I had implemented this on the start method which starts my JavaFX application:

@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("/views/ClientWindow.fxml"));
    primaryStage.setTitle("ClientWindow");
    primaryStage.setScene(new Scene(root, 600, 400));

    primaryStage.setOnCloseRequest((event) -> {
        // Do my stuff with the service
        service.stopService();
    });
    primaryStage.show();
}

Now I need to change it to my ViewModel because I need to use the service defined in the start method there. So I had two choices: Either I pass the service object to my ViewModel or I just start it there. I chose the second answer.

My problem was: How do I know when my window is being closed? This is what I did in the ViewModel:

    // Got a Label object and used it to get the scene and stage. (Ugh.)
    Stage stage = (Stage)this.labelStatus.getScene().getWindow();
    // Set the OnCloseRequest event handler to do what I did in the start() method.
    stage.setOnCloseRequest(event -> {
        // Stop services

    });

So now I am wondering if it's a good idea to do this, because it looks like I am ignoring the idea of the MVVM model. First of all, I need to get the stage using a label (what happens if I don't have a label object on my window or I do not really have to use it on the ViewModel?).

Is this the way I should go or are there better (read: nicer, more direct way) to do this?

EDIT: Show the FXML where the ModelView is defined

Look at fx:controller="viewmodels.ClientWindowViewModel"

<BorderPane minHeight="400.0" minWidth="600.0" xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1" fx:controller="viewmodels.ClientWindowViewModel">

If you try to follow the MVVM pattern then you should have a look at an application framework which does that right like, eg mvvmFX.

https://github.com/sialcasa/mvvmFX

In your setup you are treating the controller as the view model which is wrong. The controller belongs to the view and is sometimes also called "code behind". The view model has a one-to-one relationship with the view but is otherwise independent of it.

If you read the tutorials of mvvmFX you will also learn how to communicate between views and view models which will hopefully answer your question.

IMO passing the service to your controller is a better idea.

You can call FXMLLoader#getController() which will return you the instance of ClientWindowViewModel. You can have a method in this class to set the service

controller.setService(service); 

and call it in your start after you have fetched the controller instance.

Later when you are trying to close the stage, you can call the same method which you were calling earlier.

primaryStage.setOnCloseRequest((event) -> {
   // Do my stuff with the service
   service.stopService();
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM