JavaFX从FXML子访问父控制器类

使用JavaFX作为应用程序,我有一个Main.fxml文件,里面有一些fxml子文件。

我想从子控制器访问Main.fxml的MainController类。

我将尝试用一个例子更好地解释:

MainFxml:

   

MainController:

  public class MainController implements Initializable { private String string; public void setString (String string) { this.string = string; } 

ChildFxml:

     

ChildController:

  public class ChildController implements Initializable { @FXML HBox child; @FXML Button button; @FXML public void selectButton (ActionEvent event) { // here call MainController.setString("hello"); } 

我尝试在StackOverflow上找到这个解决方案,但是我需要获取已经加载的Main.fxml的Controller引用。 是否有任何方法可以从特定的窗格启动Controller? 就像是:

  // child.getParent().getController(); 

如果将fx:id分配给标记, FXMLLoader尝试将包含的fxml的控制器注入名为Controller的字段。 您可以在initialize方法中将MainController引用传递给子控制器:

    

MainController

 @FXML private ChildController childController; @Override public void initialize(URL url, ResourceBundle rb) { childController.setParentController(this); } 

ChildController

 private MainController parentController; public void setParentController(MainController parentController) { this.parentController = parentController; } @FXML private void selectButton (ActionEvent event) { this.parentController.setString("hello"); } 

但是,将ChildController与父级保持独立是更好的做法。 这可以通过在ChildController中提供一个StringProperty来完成,该StringProperty设置为父应该显示的值。

ChildController

 private final StringProperty value = new SimpleStringProperty(); public StringProperty valueProperty() { return value; } @FXML private void selectButton (ActionEvent event) { value.set("hello"); } 

ParentController

 @Override public void initialize(URL url, ResourceBundle rb) { childController.valueProperty().addListener((observable, oldValue, newValue) -> setString(newValue)); } 

我使用Singleton模型在自己的项目中解决了这个问题。 您可以使用单独的类来保持对父控制器的引用。

例如:

Global.java:

 public class Global { public static ParentControllerClass parentController; private Global() { } public static ParentControllerClass getParentController() { return mainApp; } public static void setParentController(ParentControllerClass parentController) { Global.parentController = parentController; } } 

在父控制器中,您只需要通过调用Global.setParentController(this);自身的引用传递给GlobalGlobal.setParentController(this); 。 然后,您可以使用Getter: Global.getParentController();从子Global.getParentController();访问它Global.getParentController();

这比父母和孩子共享相同的控制器更有利,因为它有助于保持代码更清晰,更易于阅读。

我自己对Java很新,这可能不是用于这种情况的最复杂的方法,但到目前为止它对我来说非常有效。