小编典典

如何从JavaFX的内部舞台获取TextField?

java

我已经为两个窗口/阶段编写了一个控制器。在MainClass中打开第一个窗口。如果用户单击按钮,则控制器中的第二个按钮。如何在applyFor()方法中从second.fxml获取TextFields?

谢谢。

@FXML
    protected void requestNewAccount(ActionEvent event) {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("second.fxml")); // TextFields in there
            Parent root = (Parent) fxmlLoader.load();
            Stage stage = new Stage();
            stage.initModality(Modality.APPLICATION_MODAL);
            stage.setTitle("Second Window");
            Scene scene = new Scene(root);
            String css = MainOnlineCustomer.class.getResource("/style.css").toExternalForm();
            scene.getStylesheets().clear();
            scene.getStylesheets().add(css);
            stage.setScene(scene);
            stage.show();
        } catch (IOException e) {
            logger.error(e);
        }
    }

    /**
     * closes the "second"-Window
     * @param event
     */
    @FXML
    protected void cancel(ActionEvent event) {
        final Node source = (Node) event.getSource();
        final Stage stage = (Stage) source.getScene().getWindow();
        stage.close();
    }

    @FXML
    protected void applyFor(ActionEvent event) {
        // get values from TextField in second.fxml here!!!
    }

阅读 622

收藏
2020-11-26

共1个答案

小编典典

在fxml之间共享控制器不是很好,除非它们具有相同的用途。在这里,这两个fxml似乎有不同的用途(帐户管理,登录或其中一个类似,并为另一个创建新帐户)。更糟糕的是,这些类没有共享相同的控制器实例,这意味着此处未使用通过使用相同的控制器可能会获得的很小(可能仅仅是)好处。您最好使用其他控制器。

由于您将其Modality.APPLICATION_MODAL用作模态,因此建议您使用showAndWait而不是show来打开新阶段。这将进入一个嵌套的事件循环,该循环使UI保持响应,并showAndWait在阶段关闭后调用后继续。

此外,将方法添加到控制器的方法中second.fxml,使您可以检索结果。

这将创建Person具有给定名称和姓氏的对象。

“主要窗口(打开“内部”阶段)

FXMLLoader loader = new FXMLLoader(getClass().getResource("second.fxml"));
Stage subStage = new Stage();
subStage.initModality(Modality.APPLICATION_MODAL);
subStage.setTitle("Second Window");
Scene scene = new Scene(loader.load());
subStage.setScene(scene);
subStage.showAndWait();

Optional<Person> result = loader.<Supplier<Optional<Person>>>getController().get();

if (result.isPresent()) {
    // do something with the result
}

“内部”内容的控制器

public class SecondController implements Supplier<Optional<Person>> {
    @FXML
    private TextField givenName;
    @FXML
    private TextField familyName;

    private boolean submitted = false;

    // handler for submit action
    @FXML
    private void submit() {
        submitted = true;
        givenName.getScene().getWindow().hide();
    }

    // handler for cancel action
    @FXML
    private void cancel() {
        givenName.getScene().getWindow().hide();
    }

    @Override
    public Optional<Person> get() {
        return submitted ? Optional.of(new Person(givenName.getText(), familyName.getText())) : Optional.empty();
    }

}

请注意,您可以通过这种方式访问​​控制器可用的任何数据。我不建议TextField直接访问任何节点(例如),因为这会使更改UI变得更加困难。

Supplier此处不必使用该接口,但我选择这样做是为了实现SecondController与主窗口之间的松散耦合。

2020-11-26