JavaFX 从 FXML 子级访问父级控制器 class
JavaFX access parent Controller class from FXML child
将 JavaFX 用于应用程序,我有一个 Main.fxml 文件,其中包含一些 fxml 子文件。
我想从子控制器访问 Main.fxml 的 MainController class。
我会尝试用一个例子来更好地解释:
MainFxml:
<HBox fx:controller="MainController.java">
<fx:include source="child.fxml"/>
</HBox>
主控制器:
public class MainController implements Initializable {
private String string;
public void setString (String string) {
this.string = string;
}
ChildFxml:
<HBox fx:id="child" fx:controller="ChildController.java">
<Button text="hello" onAction="#selectButton"></Button>
</HBox>
子控制器:
public class ChildController implements Initializable {
@FXML HBox child;
@FXML Button button;
@FXML
public void selectButton (ActionEvent event) {
// here call MainController.setString("hello");
}
我尝试了 this solution found on Whosebug,但我需要获取已加载的 Main.fxml 的控制器引用。
有没有什么方法可以让控制器从特定的窗格开始?
类似于:
// child.getParent().getController();
如果您将 fx:id
分配给 <fx:include>
标记,FXMLLoader
会尝试将包含的 fxml 的控制器注入名为 <fx:id>Controller
的字段。您可以在 initialize
方法中将 MainController
引用传递给子控制器:
<HBox fx:controller="MainController.java">
<fx:include fx:id="child" source="child.fxml"/>
</HBox>
主控制器
@FXML
private ChildController childController;
@Override
public void initialize(URL url, ResourceBundle rb) {
childController.setParentController(this);
}
子控制器
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
被设置为父级应该显示的值。
子控制器
private final StringProperty value = new SimpleStringProperty();
public StringProperty valueProperty() {
return value;
}
@FXML
private void selectButton (ActionEvent event) {
value.set("hello");
}
父控制器
@Override
public void initialize(URL url, ResourceBundle rb) {
childController.valueProperty().addListener((observable, oldValue, newValue) -> setString(newValue));
}
我在自己的项目中使用 Singleton
模型解决了这个问题。您可以使用单独的 class 来保留对 parent 控制器的引用。
例如:
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;
}
}
在您的 parent 控制器中,您只需通过调用 Global.setParentController(this);
将对自身的引用传递给 Global
class。然后,您可以使用 Getter 从 child 访问它:Global.getParentController();
这比让 parent 和 child 共享同一个控制器更可取,因为它有助于使您的代码更简洁、更易于阅读。
我自己对 Java 还很陌生,这可能不是用于这种情况的最复杂的方法,但到目前为止它对我来说效果很好。
将 JavaFX 用于应用程序,我有一个 Main.fxml 文件,其中包含一些 fxml 子文件。
我想从子控制器访问 Main.fxml 的 MainController class。
我会尝试用一个例子来更好地解释:
MainFxml:
<HBox fx:controller="MainController.java">
<fx:include source="child.fxml"/>
</HBox>
主控制器:
public class MainController implements Initializable {
private String string;
public void setString (String string) {
this.string = string;
}
ChildFxml:
<HBox fx:id="child" fx:controller="ChildController.java">
<Button text="hello" onAction="#selectButton"></Button>
</HBox>
子控制器:
public class ChildController implements Initializable {
@FXML HBox child;
@FXML Button button;
@FXML
public void selectButton (ActionEvent event) {
// here call MainController.setString("hello");
}
我尝试了 this solution found on Whosebug,但我需要获取已加载的 Main.fxml 的控制器引用。 有没有什么方法可以让控制器从特定的窗格开始? 类似于:
// child.getParent().getController();
如果您将 fx:id
分配给 <fx:include>
标记,FXMLLoader
会尝试将包含的 fxml 的控制器注入名为 <fx:id>Controller
的字段。您可以在 initialize
方法中将 MainController
引用传递给子控制器:
<HBox fx:controller="MainController.java">
<fx:include fx:id="child" source="child.fxml"/>
</HBox>
主控制器
@FXML
private ChildController childController;
@Override
public void initialize(URL url, ResourceBundle rb) {
childController.setParentController(this);
}
子控制器
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
被设置为父级应该显示的值。
子控制器
private final StringProperty value = new SimpleStringProperty();
public StringProperty valueProperty() {
return value;
}
@FXML
private void selectButton (ActionEvent event) {
value.set("hello");
}
父控制器
@Override
public void initialize(URL url, ResourceBundle rb) {
childController.valueProperty().addListener((observable, oldValue, newValue) -> setString(newValue));
}
我在自己的项目中使用 Singleton
模型解决了这个问题。您可以使用单独的 class 来保留对 parent 控制器的引用。
例如:
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;
}
}
在您的 parent 控制器中,您只需通过调用 Global.setParentController(this);
将对自身的引用传递给 Global
class。然后,您可以使用 Getter 从 child 访问它:Global.getParentController();
这比让 parent 和 child 共享同一个控制器更可取,因为它有助于使您的代码更简洁、更易于阅读。
我自己对 Java 还很陌生,这可能不是用于这种情况的最复杂的方法,但到目前为止它对我来说效果很好。