如何将参数传递给javafx中的辅助窗口?有没有办法与相应的 Controller 进行通讯?
例如:
用户从TableView
中选择一个客户,并打开一个新窗口,显示该客户的信息。
Stage newStage = new Stage();
try
{
AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
Scene scene = new Scene(page);
newStage.setScene(scene);
newStage.setTitle(windowTitle);
newStage.setResizable(isResizable);
if(showRightAway)
{
newStage.show();
}
}
newStage
将是新窗口。问题是,我找不到一种方法来告诉 Controller 在哪里寻找客户的信息(通过将id作为参数传递)。有任何想法吗?
最佳答案
推荐方法
该答案列举了将参数传递给FXML Controller 的不同机制。
对于小型应用程序,我强烈建议将参数直接从调用者传递到 Controller -它简单,直接并且不需要额外的框架。
对于更大,更复杂的应用程序,如果您想在应用程序中使用Dependency Injection或Event Bus机制,则值得研究。
将参数直接从调用者传递到 Controller
通过从FXML加载器实例检索 Controller 并将其调用在 Controller 上的方法以使用所需的数据值对其进行初始化,将自定义数据传递到FXML Controller 。
类似于以下代码:
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());
}
}
如示例代码new FXMLLoader(location)
所示,构造了一个新的FXMLLoader。该位置是一个URL,您可以通过以下方式从FXML资源生成这样的URL:new FXMLLoader(getClass().getResource("sample.fxml"));
注意不要在FXMLLoader上使用静态加载函数,否则将无法从加载程序实例中获取 Controller 。FXMLLoader实例本身对域对象一无所知。您不直接将应用程序特定的域对象传递到FXMLLoader构造函数中,而是:
该博客(由另一位作者撰写)提供了一个替代但相似的example。
在FXMLLoader上设置 Controller
CustomerDialogController dialogController =
new CustomerDialogController(param1, param2);
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
loader.setController(dialogController);
Pane mainPane = loader.load();
您可以用代码构造一个新的 Controller ,将您想要的任何参数从调用者传递到 Controller 构造函数中。构造 Controller 后,可以在调用load()
实例方法之前在FXMLLoader实例上对其进行设置。要在加载程序(在JavaFX 2.x中)上设置 Controller ,您也不能在fxml文件中定义
fx:controller
属性。由于FXML中
fx:controller
定义的限制,我个人更喜欢从FXMLLoader获取 Controller ,而不是将 Controller 设置为FXMLLoader。让 Controller 从外部静态方法中检索参数
该方法以Sergey对Javafx 2.0 How-to Application.getParameters() in a Controller.java file的回答为例。
使用依赖项注入(inject)
通过允许您在FXMLLoader上设置自定义 Controller 工厂,FXMLLoader支持诸如Guice,Spring或Java EE CDI的依赖项注入(inject)系统。这提供了一个回调,您可以使用该回调创建具有由相应依赖项注入(inject)系统注入(inject)的依赖值的 Controller 实例。
回答中提供了JavaFX应用程序和Spring Controller 依赖注入(inject)的示例:
一个非常好的,干净的依赖项注入(inject)方法以afterburner.fx framework为例,并使用了一个示例air-hacks application。 afterburner.fx依靠JEE6 javax.inject执行依赖项注入(inject)。
使用事件总线
最初的FXML规范创建者和实现者Greg Brown通常建议考虑使用事件总线(例如Guava EventBus)在FXML实例化 Controller 和其他应用程序逻辑之间进行通信。
The EventBus is a simple but powerful publish/subscribe API with annotations that allows POJOs to communicate with each other anywhere in a JVM without having to refer to each other.
后续问答
on first method, why do you return Stage? The method can be void as well because you already giving the command show(); just before return stage;. How do you plan usage by returning the Stage
这是一个解决问题的功能。从
showCustomerDialog
函数返回一个阶段,以便以后可能希望做某事的外部类可以存储对该阶段的引用,例如,根据在主窗口中单击按钮隐藏该阶段。另一种面向对象的解决方案可以将功能和阶段引用封装在CustomerDialog对象中,或者具有CustomerDialog扩展阶段。一个自定义对话框的面向对象的界面的完整示例,该示例对话框封装了FXML, Controller 和模型数据,超出了此答案的范围,但对于那些愿意创建一个的人来说,可能是一个有值(value)的博客文章。由StackOverflow用户@dzim 提供的其他信息
Spring Boot依赖注入(inject)示例
关于如何做的问题“Spring Boot Way”,有一个关于JavaFX 2的讨论,我在所附的永久链接中对此进行了解答。
该方法仍然有效,并已在2016年3月的Spring Boot v1.3.3。中进行了测试。
https://stackoverflow.com/a/36310391/1281217
有时,您可能希望将结果传递回给调用者,在这种情况下,您可以检查出相关问题的答案:
关于javafx - 传递参数JavaFX FXML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16744129/