Javafx 将登录令牌从 LoginController 传递到 CalendarController

Javafx pass login token from LoginController to CalendarController

我正在使用 Angela 的屏幕管理框架,我正在尝试编写一个非常简单的 日历应用程序。在编写 UI 和控制器并使用上述框架时,所有屏幕都会在程序启动时立即初始化。这意味着我不知道用户何时实际查看某个视图。

我需要来自服务器的 login-token(在 LoginController 中分配)来触发 CalendarController 中某种类型的更改值事件当前 运行 在后台(我想)。目前我不知道 Calendar.fxml 何时可见 and/if 用户已登录,因此我不知道如何构建我的逻辑以使函数在 [=12= 中启动] 在设置 登录令牌 之后。

在这里呆了几天,如果有任何帮助,我们将不胜感激。我尝试使用 ObservableList 和 Listlistener 接口无济于事。这是我的LoginController的相应部分。 TokenFactory 是一个 class 的静态字段和方法(主要是为了调试)。

    @FXML
public boolean login() throws JSONException, UnirestException {
    if(validateUsernameField() && validatePasswordField()) {
        HttpResponse<JsonNode> jsonResponse = Unirest.post(TokenFactory.getSERVER_ADR())
          .field("username", usernameField.getText())
          .field("password", passwordField.getText())
          .asJson();
        if ( ((String) jsonResponse.getBody().getObject().get("message")).equalsIgnoreCase("OK")) {
            String token = ((String) jsonResponse.getBody().getObject().get("token"));
            //Ignore JSON to debug
            TokenFactory.setToken("fakeToken123");  
            responseLabel.setText("Logging in...");
            myController.setScreen(ScreensFramework.CalendarID);
            return true;            
         } else {
            responseLabel.setText("Wrong username or password.");
            passwordField.clear();
        }
    } return false;
}

//Screen management
ScreensController myController;

这里有很多选择:

第一个选项:不是在启动时加载所有屏幕,而是在登录成功时只加载日历屏幕。那么你的 CalendarControllerinitialize() 方法基本上可以假定用户已登录。

第二个选项:修改框架,使其在加载控制器时return引用控制器,或者在加载后让您访问控制器。第一个版本看起来像:

public <T extends ControlledScreen> T loadScreen(String name, String resource) {
    try {
        FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
        Parent loadScreen = (Parent) myLoader.load();
        T myScreenControler = myLoader.getController();
        myScreenControler.setScreenParent(this);
        addScreen(name, loadScreen);
        return myScreenControler ;
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return null;
    }
}

现在,当您首次加载日历屏幕时,您可以获得对其控制器的引用:

CalendarController calendarController = screensController.loadScreen(...);

所以现在当您成功登录时,您可以调用 calendarController 上的方法。请注意 loadScreen(...) 的 return 类型已更改,因此您可能需要相应地修改其他代码。

或者,您可以在 ScreensController 中引入新地图:

public class ScreensController extends StackPane {

    private Map<String, Node> screens = new HashMap<>();
    private Map<String, ControlledScreen> controllers = new HashMap<>();

    // ...

    public boolean loadScreen(String name, String resource) {
        try {
            FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
            Parent loadScreen = (Parent) myLoader.load();
            ControlledScreen myScreenControler = ((ControlledScreen) myLoader.getController());
            myScreenControler.setScreenParent(this);

            addScreen(name, loadScreen);

            // also save the controller:
            controllers.put(name, myScreenControler);

            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return false;
        }
    }

    // ...

    // new method to retrieve controller:

    public ControlledScreen getController(String name) {
        return controllers.get(name);
    }

    // modify the remove method to clean up the controller as well:

    public boolean unloadScreen(String name) {
        if (screens.remove(name) == null) {
            System.out.println("Screen didn't exist");
            return false;
        } else {
            controllers.remove(name);
            return true;
        }
    }
}

现在当用户登录时,你可以做

CalendarController calendarController = 
    (CalendarController) myController.getController(ScreensFramework.CalendarID);

并在 calendarController.

上调用您需要的任何方法

第三个选项:创建一个BooleanProperty loggedIn = new SimpleBooleanProperty();并在用户登录时将其设置为true。然后安排你的CalendarController能够观察到它并在用户登录时做出反应。它改变。我不太喜欢这个选项,因为安排 CalendarController 看到 loggedIn 属性 几乎肯定会涉及该控制器和另一个 class 之间的某种额外耦合,但它是可能的。