我已经为两个窗口/阶段编写了一个控制器。在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!!! }
在fxml之间共享控制器不是很好,除非它们具有相同的用途。在这里,这两个fxml似乎有不同的用途(帐户管理,登录或其中一个类似,并为另一个创建新帐户)。更糟糕的是,这些类没有共享相同的控制器实例,这意味着此处未使用通过使用相同的控制器可能会获得的很小(可能仅仅是)好处。您最好使用其他控制器。
由于您将其Modality.APPLICATION_MODAL用作模态,因此建议您使用showAndWait而不是show来打开新阶段。这将进入一个嵌套的事件循环,该循环使UI保持响应,并showAndWait在阶段关闭后调用后继续。
Modality.APPLICATION_MODAL
showAndWait
show
此外,将方法添加到控制器的方法中second.fxml,使您可以检索结果。
second.fxml
这将创建Person具有给定名称和姓氏的对象。
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变得更加困难。
TextField
Supplier此处不必使用该接口,但我选择这样做是为了实现SecondController与主窗口之间的松散耦合。
Supplier
SecondController