简体   繁体   English

JavaFX在ViewModel上使用舞台

[英]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: 我已经在启动JavaFX应用程序的start方法上实现了这一点:

@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. 现在,我需要将其更改为ViewModel,因为我需要使用start方法中定义的服务。 So I had two choices: Either I pass the service object to my ViewModel or I just start it there. 因此,我有两种选择:要么将服务对象传递给ViewModel,要么就从那里启动它。 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: 这是我在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. 所以现在我想知道这样做是否是个好主意,因为看起来我正在忽略MVVM模型的主意。 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?). 首先,我需要使用标签作为舞台(如果我的窗口上没有标签对象,或者我真的不必在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 编辑:显示定义了ModelView的FXML

Look at fx:controller="viewmodels.ClientWindowViewModel" 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. 如果您尝试遵循MVVM模式,那么应该看看能做到这一点的应用程序框架,例如mvvmFX。

https://github.com/sialcasa/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. 如果您阅读了mvvmFX的教程,您还将学习如何在视图和视图模型之间进行通信,这有望回答您的问题。

IMO passing the service to your controller is a better idea. IMO将服务传递给您的控制器是一个更好的主意。

You can call FXMLLoader#getController() which will return you the instance of ClientWindowViewModel. 您可以调用FXMLLoader#getController() ,它将返回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();
}); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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