在 javafx 对话框操作上编辑父阶段元素

On javafx dialog action edit parent stage elements

我有一个带有两个按钮的 JavaFX 应用程序:"Edit" 和 "Save" 以及一个文本字段 "textField1"。

最初,文本字段 "textField1" 和 "Save" 按钮被禁用(fxml 使用场景生成器构建,因此可编辑在那里设置为 false)。

当用户单击按钮 "Edit" 时,会弹出一个登录对话框。如果用户输入了正确的凭据,那么我想隐藏弹出窗口并解锁(可编辑)文本字段 "textField1" 和按钮 "Save" 以便用户能够编辑文本字段值并将其保存到数据库中。

保存后我想再次锁定(不可编辑)"Save" 按钮和文本字段 "textField1"。

这是我的主应用程序 class:

public class Main extends Application {
    ...
    private Stage theStage;
    ...
    public static void main(String[] args) throws IOException {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws IOException {
        //setTheStage(primaryStage);
        try {
            AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("FXMLDocument.fxml"));
            Scene scene = new Scene(page, initWidth, initHeight);
            primaryStage.setScene(scene);

            currentPane(scene, page);

            primaryStage.show();

        } catch (IOException ex) {
            log.log(Level.INFO, null, ex);            
        }
    }

这是我的主场景(FXMLDocument.fxml控制器):

public class FXMLDocumentController implements Initializable {
    @FXML
    private Button save;
    @FXML 
    private Button edit;
    @FXML
    private TextField textField1;
    ...
    private Stage primaryStage;
    @Override
    @FXML
    public void initialize(URL url, ResourceBundle rb) {
        ...
        //to do?
    }
    ...
    //edit button action
    @FXML
    private void onConfigParametersEdit(ActionEvent event) throws IOException, SchedulerException {

        log.info("You clicked me!");
        FXMLLoader fl = new FXMLLoader();
        fl.setLocation(getClass().getResource("LoginDialog.fxml"));
        fl.load();
        Parent root = fl.getRoot();

        Stage modal_dialog = new Stage(StageStyle.DECORATED);
        modal_dialog.initModality(Modality.WINDOW_MODAL);
        modal_dialog.initOwner(primaryStage);
        Scene scene = new Scene(root);

        LoginDialogController t1 = (LoginDialogController)fl.getController();
        t1.setStage(modal_dialog);
        modal_dialog.setScene(scene);
        modal_dialog.show();
    }

    public void onConfigParametersSave(ActionEvent event) throws IOException {
        String textField1Str = textField1.getText();
        //some code to save it to the database
    }
    ...
}

最后是 LoginDialog.fxml 控制器:

public class LoginDialogController implements Initializable {

    @FXML
    private Button login;
    @FXML 
    private Button cancel;

    @FXML
    private TextField username;
    @FXML
    private TextField password;

    private Stage parentStage;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        //to do
    }

    void setStage(Stage temp) {
         parentStage = temp;
    }

    @FXML
    private void onCancelActionEvent(ActionEvent event) {
        log.info("You clicked cancel!");
        parentStage.close();
    }

    @FXML
    private void onLoginActionEvent(ActionEvent event) {
        String usernameStr = username.getText();
        String passwordStr = password.getText();
        log.info("You have entered username: " + usernameStr + " and password: " + passwordStr);
        if(usernameStr.equals("admin") && passwordStr.equals("admin")) {
            log.info("login correct");
            parentStage.close();
            // how am i going to unlock Save button & textField1 into my "parent" scene?
        } else {
            log.info("login error");
        }
    }

问题是如何在成功登录后返回 FXMLDocument.fxml 并解锁“保存”按钮和 textField1?

好的,我不知道这是否是最佳解决方案,但我设法在这两个场景之间绑定了 textField1 textField 和 Save 按钮,并通过这种方式实现了请求的功能:

我在 FXMLDocument.fxml 控制器中添加了:

@FXML
private void onConfigParametersEdit(ActionEvent event) throws IOException, SchedulerException {

    scheduler.shutdown();

    log.info("You clicked me!");
    FXMLLoader fl = new FXMLLoader();
    fl.setLocation(getClass().getResource("LoginDialog.fxml"));
    fl.load();
    Parent root = fl.getRoot();

    Stage modal_dialog = new Stage(StageStyle.DECORATED);
    modal_dialog.initModality(Modality.WINDOW_MODAL);
    modal_dialog.initOwner(primaryStage);
    Scene scene = new Scene(root);

    LoginDialogController t1 = (LoginDialogController)fl.getController();

    //added these two lines to bind 2nd controller property values
    t1.save2nd = save;
    t1.textField12nd = textField1;

    t1.setStage(modal_dialog);
    modal_dialog.setScene(scene);
    modal_dialog.show();

}

在第二个控制器中,我刚刚添加了两个属性:textField1 和 save2nd 以及成功登录时的 setDisable(false):

public class LoginDialogController implements Initializable {
    ...
    //just adding the additional fields - other remains the same
    public Button save2nd;
    public TextField workstationIp2nd;
    ...
    @FXML
    private void onLoginActionEvent(ActionEvent event) {

        String usernameStr = username.getText();
        String passwordStr = password.getText();
        log.info("You have entered username: " + usernameStr + " and password: " + passwordStr);
        if(usernameStr.equals("admin") && passwordStr.equals("admin")) {
            log.info("login correct");

            save2nd.setDisable(false);
            workstationIp2nd.setDisable(false);

            parentStage.close();

        } else {
            log.info("login error");
        }
    }

有几种方法可以做到。这建议您在 LoginDialogController 中创建一个额外的字段,以保持用户凭据是否正确的状态,并将其绑定到已在 FXMLDocumentController.

中定义的控件
public class LoginDialogController implements Initializable {

   ...
   private BooleanProperty loginSuccessful = new SimpleBooleanProperty();

   public loginSuccessfulProperty() {
        return loginSuccessful;
   }

   ...

}

然后当用户成功登录时更新这个字段。

@FXML
private void onLoginActionEvent(ActionEvent event) {
    ...
    if(usernameStr.equals("admin") && passwordStr.equals("admin")) {
        log.info("login correct");
        parentStage.close();
        loginSuccessful.set(true);
    } else {
        log.info("login error");
    }
}

在您的 FXMLDocumentController 中,让控件 editableProperty() 绑定到这个新定义的属性。

public class FXMLDocumentController implements Initializable {

    private void onConfigParametersEdit(ActionEvent event) 
         LoginDialogController t1 = (LoginDialogController)fl.getController();
        t1.setStage(modal_dialog);
        textField1.editableProperty().bind(t1.loginSuccessfulProperty());
        save.editableProperty().bind(t1.loginSuccessfulProperty());
    }
}