将控制器连接到您的应用程序fxml

时间:2018-01-13 20:07:41

标签: java javafx fxml

我正在创建一个需要用户设置密码的应用程序。我的密码场景是用fxml编写的。在用户单击注册按钮后,我希望控制器通知主应用程序并为其提供密码以便它可以使用它目前我正在通过子类化控制器这样做

    class RegisterClass
{
    private Stage stage = new Stage();
    private Scene scene;
    @FXML PasswordField secondpass;
    @FXML PasswordField firstpass;
    @FXML Label error;
    @FXML Button register;
    public RegisterClass()
    {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/com/quagrum/resources/fxml/register.fxml"));
        Pane par = null;


        fxmlLoader.setController(this);
         try {
                par = fxmlLoader.load();
            } catch (IOException exception) {
                throw new RuntimeException(exception);
            }
         scene= new Scene(par,219,240);
         stage.setScene(scene);
         stage.getIcons().add(new Image(getClass().getResource("/com/quagrum/resources/images/NewQuagrumIco.png").toString()));
            scene.setOnKeyPressed(new EventHandler<KeyEvent>()
            {
                @Override
                public void handle(KeyEvent ke)
                {
                    if (ke.getCode().equals(KeyCode.ENTER))
                    {
                        register.fire();
                    }
                }
            });
            stage.setOnCloseRequest(e->{
                System.exit(0);
            });
            stage.showAndWait();
    }
    @FXML
    private void initialize() {

        register.setOnAction(e->{

            if(firstpass.getText().equals(secondpass.getText()))
            {
                if(firstpass.getText().length()==0)
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }else
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }

            }else
            {
                error.setText("Passwords do not match");
                error.setVisible(true);
            }
        });

    }
}
private void register()//this one setups all the accounts with the new password
{
    RegisterClass register = new RegisterClass();
}

然而,这使我在父类中的代码更长,因为我也对登录页面做了​​同样的事情。所以我的问题是,有没有办法可以创建一个单独的控制器类,它将与调用者交互并发送密码,或者这是目前最好的方法。

1 个答案:

答案 0 :(得分:0)

  

抱歉,我不知道构造函数中的阻塞意味着什么。

这是对stage.showAndWait();构造函数中RegisterClass的调用。就OOP而言,这是一个非常糟糕的设计。

您可以通过不同的机制从此控制器获取数据。最简单的方法是使geter返回新密码。 Supplier<T>的实现正是如此(使用接口不是强制性的,但稍后会帮助您更轻松地与系统中的其他组件进行通信,而不违反OOP原则)

public class RegisterClass implements Supplier<Optional<String>> {

    ...

    public Optional<String> showAndWait() {
        stage.showAndWait();
        return get();
    }

    @Override
    public Optional<String> get() {
        return Optional.ofNullable(password);
    }
}

因此,调用有点不同,但您已经有了获取新密码的机制

RegisterClass register = new RegisterClass();
register.showAndWait().ifPresent(password -> {
    System.out.println("New password: " + password);
});

另一个选择是使用Consumer<T>注册RegisterClass以获取新密码

public class RegisterClass {
    private Consumer<Optional<String>> passwordHandler;

    ...

    @FXML
    private void initialize() {
        register.setOnAction(e->{
            if(firstpass.getText().equals(secondpass.getText()))
            {
                if(firstpass.getText().length()==0)
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }else
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }

                if(passwordHandler != null) {
                    passwordHandler.accept(Optional.ofNullable(password));
                }

            }else
            {
                error.setText("Passwords do not match");
                error.setVisible(true);
            }
        });
    }

    ...

    public void addPasswordHandler(Consumer<Optional<String>> passwordHandler) {
        this.passwordHandler = passwordHandler;
    }

    public void showAndWait() {
        stage.showAndWait();
    }
}

在这种情况下,使用起来有点复杂,因为您必须创建Consumer<T>实例并将其提交到RegisterClass

public class MainController {
    private Consumer<Optional<String>> passwordHandler = password -> {
        System.out.println(password);
    };

    @FXML
    private void handleRegister(ActionEvent event) {
        RegisterClass register = new RegisterClass();
        register.addPasswordHandler(passwordHandler);
        register.showAndWait();
    }
}

可以使用Singleton扩展后一个示例,以避免Consumer<T>的手动注册。如果您有很多调用的控制器调用并且不希望通过在它们之间传递参数来使逻辑复杂化,那么这很好。

public class RegisterClass {
    ...

    @FXML
    private void initialize() {
        register.setOnAction(e->{
            if(firstpass.getText().equals(secondpass.getText()))
            {
                if(firstpass.getText().length()==0)
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }else
                {
                    password=firstpass.getText();
                    createLock();
                    stage.close();
                }

                Consumer<Optional<String>> passwordHandler = MainController.getPasswordHandler();
                if(passwordHandler != null) {
                    passwordHandler.accept(Optional.ofNullable(password));
                }

            }else
            {
                error.setText("Passwords do not match");
                error.setVisible(true);
            }
        });
    }

    ...
    public void showAndWait() {
        stage.showAndWait();
    }
}

这是用法

public class MainController {
    private static Consumer<Optional<String>> passwordHandler;

    public static Consumer<Optional<String>> getPasswordHandler() {
        return passwordHandler;
    }

    @FXML
    private void initialize() {
        passwordHandler = password -> {
            System.out.println(password);
        };
    }

    @FXML
    private void handleRegister(ActionEvent event) {
        RegisterClass register = new RegisterClass();
        register.showAndWait();
    }
}