【问题标题】:How can I get TextField from inner stage in JavaFX?如何从 JavaFX 的内部阶段获取 TextField?
【发布时间】:2016-06-27 19:56:27
【问题描述】:

我已经为两个窗口/阶段编写了一个控制器。 第一个窗口在 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!!!
    }

【问题讨论】:

  • 将操作按钮绑定到applyFor方法,并从second.fxml为TextField设置一个Id。

标签: java javafx


【解决方案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();
    }

}

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

这里使用Supplier接口不是必须的,但是我选择这样做是为了实现SecondController和主窗口之间的松耦合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 2015-12-31
    • 2012-10-26
    • 2013-03-26
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多