使用MVC
这个回答主要集中在将参数从调用类传递给控制器的直接调用上。
如果相反,你想要解耦调用者和控制器,并使用一个更通用的架构,包括一个具有可设置和可侦听属性的模型类来实现控制器之间的通信,请参阅以下基本概述:
使用JavaFx应用MVC
推荐的方法
这个答案列举了向FXML控制器传递参数的不同机制。
对于小型应用程序,我强烈建议直接将参数从调用者传递给控制器——这很简单,直接,不需要额外的框架。
对于更大、更复杂的应用程序,如果您想在应用程序中使用依赖注入或事件总线机制,那么值得研究一下。
直接从调用者向控制器传递参数
通过从FXML加载器实例检索控制器并调用控制器上的方法以使用所需的数据值初始化控制器,将自定义数据传递给FXML控制器。
类似于下面的代码:
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(loader.load())
);
CustomerDialogController controller = loader.getController();
controller.initData(customer);
stage.show();
return stage;
}
...
class CustomerDialogController {
@FXML private Label customerName;
void initialize() {}
void initData(Customer customer) {
customerName.setText(customer.getName());
}
}
一个新的FXMLLoader被构造,如示例代码所示,即new FXMLLoader(location)。该位置是一个URL,您可以通过以下方式从FXML资源生成这样一个URL:
new FXMLLoader(getClass().getResource("sample.fxml"));
注意不要在FXMLLoader上使用静态加载函数,否则您将无法从加载器实例中获得控制器。
FXMLLoader实例本身从来不知道任何关于域对象的信息。你不直接传递应用程序特定的域对象到FXMLLoader构造函数,而是:
在指定位置根据fxml标记构造一个FXMLLoader
从FXMLLoader实例获取一个控制器。
调用检索到的控制器上的方法,为控制器提供对域对象的引用。
这篇博客(由另一位作者撰写)提供了一个类似的替代例子。
在FXMLLoader上设置控制器
CustomerDialogController dialogController =
new CustomerDialogController(param1, param2);
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
loader.setController(dialogController);
Pane mainPane = loader.load();
你可以在代码中构造一个新的控制器,把你想从调用者那里得到的任何参数传递给控制器构造函数。一旦构建了控制器,就可以在调用load()实例方法之前在FXMLLoader实例上设置它。
要在加载器上设置控制器(在JavaFX 2.x中),你不能在你的fxml文件中定义fx:controller属性。
由于FXML中fx:controller定义的限制,我个人更喜欢从FXMLLoader中获取控制器,而不是将控制器设置到FXMLLoader中。
让控制器从外部静态方法检索参数
Sergey在Controller.java文件中对Javafx 2.0 How-to Application.getParameters()的回答举例说明了这种方法。
使用依赖注入
FXMLLoader支持依赖注入系统,如Guice, Spring或Java EE CDI,允许你在FXMLLoader上设置自定义控制器工厂。这提供了一个回调,您可以使用该回调创建控制器实例,其中包含由各自的依赖注入系统注入的依赖值。
下面给出了一个JavaFX应用程序和控制器依赖注入Spring的示例:
在JavaFX中添加Spring依赖注入(JPA Repo, Service)
加力是一种非常好的、干净的依赖注入方法。Fx框架与示例air-hacks应用程序使用它。加力燃烧室。fx依赖于JEE6 javax。注入以执行依赖项注入。
使用事件总线
Greg Brown是FXML规范的最初创建者和实现者,他经常建议考虑使用事件总线,例如Guava EventBus,用于FXML实例化控制器和其他应用程序逻辑之间的通信。
EventBus是一个简单但功能强大的带有注释的发布/订阅API,它允许pojo在JVM中的任何地方相互通信,而不必相互引用。
后续的问答
关于第一种方法,你为什么返回舞台?这个方法也可以是空的,因为你已经给出了show()命令;在返回阶段之前;。如何通过返回Stage来计划使用
It is a functional solution to a problem. A stage is returned from the showCustomerDialog function so that a reference to it can be stored by an external class which may wish to do something, such as hide the stage based on a button click in the main window, at a later time. An alternate, object-oriented solution could encapsulate the functionality and stage reference inside a CustomerDialog object or have a CustomerDialog extend Stage. A full example for an object-oriented interface to a custom dialog encapsulating FXML, controller and model data is beyond the scope of this answer, but may make a worthwhile blog post for anybody inclined to create one.
StackOverflow用户@ zim提供的附加信息
Spring引导依赖注入示例
关于如何做到“Spring Boot Way”的问题,有一个关于JavaFX 2的讨论,我在附件中回答了这个问题。
该方法仍然有效,并在2016年3月Spring Boot v1.3.3.RELEASE上进行了测试:
https://stackoverflow.com/a/36310391/1281217
有时,你可能想要将结果返回给调用者,在这种情况下,你可以检查出相关问题的答案:
JavaFX FXML从控制器A传递到控制器B并返回的参数