在通过 fxml 设置的两个 JavaFX windows 之间传递值?
Pass value between two JavaFX windows that are setup through fxml?
我了解如何在两个表单之间传递值 https://www.youtube.com/watch?v=HFAsMWkiLvg
问题出在视频中的处理方式上。 (即静态)。由于使用了 getClass() 方法,我在静态方法内部无法使 FXMLLoaders 工作。它只是非静态的。
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 内部,我将方法设置为 运行,它实际上是针对数据库检查 username/password。所有这些都是在我的 loginController class 中完成的。一旦成功,它就会这样做。 (上面我为 loginButton 声明了我的 @FXML 钩子)
Stage stage = (Stage) loginButton.getScene().getWindow();
stage.close();
我目前的程序设置方式是在用户登录之前将所有菜单设置为禁用。我已经设置了一个非静态方法来重新启用所有内容,但我无法调用它是因为在关闭我的第二个 window.
之前我无法弥合静态/非静态之间的差距
谢谢,
在 UI 的两个或多个不同部分之间共享数据的普遍接受的方法是使用 MVC/MVP 类型的方法。在这些模式中,您将数据封装在 "model"("M" 中),以便可以观察到数据并在数据发生变化时发送通知。然后 UI 的一部分可以更新模型,而 UI 的其他部分正在观察它,如果它发生变化将得到通知。
JavaFX 通过为您实现 observable properties 使这变得特别容易,它只是包装值并使添加在更改时收到通知的侦听器变得容易。
所以在这个例子中你可以这样做:
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
属性(负),因此菜单项自动启用。如果您有一个 "Log Out" 按钮,只需将其设置 loggedIn
属性 为 false
,菜单项将再次被禁用。
我了解如何在两个表单之间传递值 https://www.youtube.com/watch?v=HFAsMWkiLvg
问题出在视频中的处理方式上。 (即静态)。由于使用了 getClass() 方法,我在静态方法内部无法使 FXMLLoaders 工作。它只是非静态的。
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 内部,我将方法设置为 运行,它实际上是针对数据库检查 username/password。所有这些都是在我的 loginController class 中完成的。一旦成功,它就会这样做。 (上面我为 loginButton 声明了我的 @FXML 钩子)
Stage stage = (Stage) loginButton.getScene().getWindow();
stage.close();
我目前的程序设置方式是在用户登录之前将所有菜单设置为禁用。我已经设置了一个非静态方法来重新启用所有内容,但我无法调用它是因为在关闭我的第二个 window.
之前我无法弥合静态/非静态之间的差距谢谢,
在 UI 的两个或多个不同部分之间共享数据的普遍接受的方法是使用 MVC/MVP 类型的方法。在这些模式中,您将数据封装在 "model"("M" 中),以便可以观察到数据并在数据发生变化时发送通知。然后 UI 的一部分可以更新模型,而 UI 的其他部分正在观察它,如果它发生变化将得到通知。
JavaFX 通过为您实现 observable properties 使这变得特别容易,它只是包装值并使添加在更改时收到通知的侦听器变得容易。
所以在这个例子中你可以这样做:
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
属性(负),因此菜单项自动启用。如果您有一个 "Log Out" 按钮,只需将其设置 loggedIn
属性 为 false
,菜单项将再次被禁用。