在通过fxml设置的两个JavaFX窗口之间传递值?

在通过fxml设置的两个JavaFX窗口之间传递值?,java,javafx,javafx-8,scenebuilder,Java,Javafx,Javafx 8,Scenebuilder,我知道如何在两种形式之间传递值 问题在于视频中的处理方式。(也就是说是静态的)。由于使用了getClass()方法,当FXMLLoader位于静态方法内部时,我无法使其工作。它只是非静态的。 getClass().getResource(“myFile.fxml”) 下面是我如何加载我的第二个表单 try { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("LoginForm.fxml"));

我知道如何在两种形式之间传递值

问题在于视频中的处理方式。(也就是说是静态的)。由于使用了getClass()方法,当FXMLLoader位于静态方法内部时,我无法使其工作。它只是非静态的。
getClass().getResource(“myFile.fxml”)

下面是我如何加载我的第二个表单

try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("LoginForm.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();
        Stage stage = new Stage();
        stage.initModality(Modality.APPLICATION_MODAL);
        stage.setTitle("HWI - Login");
        stage.setResizable(false);
        stage.setScene(new Scene(root1));
        stage.showAndWait();

    } catch (Exception e) {
        e.printStackTrace();
    }
在scenebuilder内部,我将该方法设置为在其基本上检查DB的用户名/密码时运行。所有这些都是在我的loginController类中完成的。一旦成功,它就会这样做。(上面我为登录按钮声明了@FXML钩子)

我目前设置程序的方式是在用户登录之前将所有菜单设置为禁用。我已经设置了一个非静态方法来重新启用所有内容,但我无法调用它,因为在关闭第二个窗口之前,我无法弥合静态/非静态之间的差距


谢谢,

在UI的两个或多个不同部分之间共享数据的普遍接受的方法是使用MVC/MVP类型的方法。在这些模式中,您将数据封装在一个“模型”(或“M”)中,以便在数据发生变化时可以对其进行观察并发送通知。然后,UI的一部分可以更新模型,如果模型发生更改,则会通知正在观察模型的UI的其他部分

JavaFX通过为您实现使这一点变得特别容易,它只包装值,并使添加侦听器变得容易,如果它们发生更改,就会收到通知

因此,在本例中,您可以执行以下操作:

public class AuthenticationState {

    private final BooleanProperty loggedIn = new SimpleBooleanProperty(false);

    public BooleanProperty loggedInProperty() {
        return loggedIn ;
    }

    public final boolean isLoggedIn() {
        return loggedInProperty().get();
    }

    public final void setLoggedIn(boolean loggedIn) {
        loggedInProperty().set(loggedIn);
    }

    private final StringProperty userName = new SimpleStringProperty();

    public StringProperty userNameProperty() {
        return userName ;
    }

    public final String getUserName() {
        return userNameProperty().get();
    }

    public final void setUserName(String userName) {
        userNameProperty().set(userName);
    }

    // other properties as needed, e.g. IntegerProperty logInAttempts , etc.
}
现在,主控制器可以执行以下操作:

public class MainController {

    @FXML
    private final MenuItem deleteAllDataMenuItem ;

    private AuthenticationState authenticationState ;

    public void initialize() {

        authenticationState = new AuthenticationState();

        deleteAllDataMenuItem.disableProperty()
            .bind(authenticationState.loggedInProperty().not());

    }

    @FXML
    public void logIn() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("LoginForm.fxml"));
            Parent root1 = (Parent) fxmlLoader.load();

            LoginController loginController = fxmlLoader.getController();
            loginController.setAuthenticationState(authenticationState);

            Stage stage = new Stage();
            stage.initModality(Modality.APPLICATION_MODAL);
            stage.setTitle("HWI - Login");
            stage.setResizable(false);
            stage.setScene(new Scene(root1));
            stage.showAndWait();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
您的登录控制器可以如下所示:

public class LoginController {

    private AuthenticationState authenticationState ;

    public void setAuthenticationState(AuthenticationState authenticationState) {
        this.authenticationState = authenticationState ;
    }

    @FXML
    public void login() {
        // check login:
        boolean loginSuccessful = ... ;

        authenticationState.setLoggedIn(loginSuccessful);

        // ...
    }
}

现在,当用户登录时,登录控制器将
authenticationState
中的
loggedIn
属性设置为
true
。由于菜单项的禁用状态绑定到
loggedIn
属性(负),因此菜单项将自动启用。如果您有一个“注销”按钮,只需将
loggedIn
属性设置为
false
,菜单项将再次被禁用。

在UI的两个或多个不同部分之间共享数据的普遍接受的方法是使用MVC/MVP类型的方法。在这些模式中,您将数据封装在一个“模型”(或“M”)中,以便在数据发生变化时可以对其进行观察并发送通知。然后,UI的一部分可以更新模型,如果模型发生更改,则会通知正在观察模型的UI的其他部分

JavaFX通过为您实现使这一点变得特别容易,它只包装值,并使添加侦听器变得容易,如果它们发生更改,就会收到通知

因此,在本例中,您可以执行以下操作:

public class AuthenticationState {

    private final BooleanProperty loggedIn = new SimpleBooleanProperty(false);

    public BooleanProperty loggedInProperty() {
        return loggedIn ;
    }

    public final boolean isLoggedIn() {
        return loggedInProperty().get();
    }

    public final void setLoggedIn(boolean loggedIn) {
        loggedInProperty().set(loggedIn);
    }

    private final StringProperty userName = new SimpleStringProperty();

    public StringProperty userNameProperty() {
        return userName ;
    }

    public final String getUserName() {
        return userNameProperty().get();
    }

    public final void setUserName(String userName) {
        userNameProperty().set(userName);
    }

    // other properties as needed, e.g. IntegerProperty logInAttempts , etc.
}
现在,主控制器可以执行以下操作:

public class MainController {

    @FXML
    private final MenuItem deleteAllDataMenuItem ;

    private AuthenticationState authenticationState ;

    public void initialize() {

        authenticationState = new AuthenticationState();

        deleteAllDataMenuItem.disableProperty()
            .bind(authenticationState.loggedInProperty().not());

    }

    @FXML
    public void logIn() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("LoginForm.fxml"));
            Parent root1 = (Parent) fxmlLoader.load();

            LoginController loginController = fxmlLoader.getController();
            loginController.setAuthenticationState(authenticationState);

            Stage stage = new Stage();
            stage.initModality(Modality.APPLICATION_MODAL);
            stage.setTitle("HWI - Login");
            stage.setResizable(false);
            stage.setScene(new Scene(root1));
            stage.showAndWait();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
您的登录控制器可以如下所示:

public class LoginController {

    private AuthenticationState authenticationState ;

    public void setAuthenticationState(AuthenticationState authenticationState) {
        this.authenticationState = authenticationState ;
    }

    @FXML
    public void login() {
        // check login:
        boolean loginSuccessful = ... ;

        authenticationState.setLoggedIn(loginSuccessful);

        // ...
    }
}

现在,当用户登录时,登录控制器将
authenticationState
中的
loggedIn
属性设置为
true
。由于菜单项的禁用状态绑定到
loggedIn
属性(负),因此菜单项将自动启用。如果您有一个“注销”按钮,只要让它将
loggedIn
属性设置为
false
,菜单项就会再次被禁用。

getResource
方法可以静态使用:
ExampleClass.class.getResource
但是有比静态控制器类更好的方法。请看,在控制器中使任何东西(常数除外)保持静态通常是一个非常糟糕的主意。我不太清楚您想做什么:您想从登录控制器与主控制器通信,还是相反?(第二种方法很简单;第一种方法有点棘手,因此如果是第一种方法,请精确地说明您想要通信的内容。)
getResource
方法可以以静态方式使用:
ExampleClass.class.getResource
但是有比静态控制器类更好的方法。请看,在控制器中使任何东西(常数除外)保持静态通常是一个非常糟糕的主意。我不太清楚您想做什么:您想从登录控制器与主控制器通信,还是相反?(第二个很简单;第一个有点棘手,因此如果是第一个,请准确地说出您想要传达的内容。)感谢您的详细解释!谢谢你的详细解释!