传递参数 JavaFX FXML [英] Passing Parameters JavaFX FXML

查看:66
本文介绍了传递参数 JavaFX FXML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将参数传递给 javafx 中的辅助窗口?有没有办法和对应的控制器通信?

How can I pass parameters to a secondary window in javafx? Is there a way to communicate with the corresponding controller?

例如:用户从 TableView 中选择一个客户,然后打开一个新窗口,显示客户的信息.

For example: The user chooses a customer from a TableView and a new window is opened, showing the customer's info.

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 将是新窗口.问题是,我找不到告诉控制器在哪里查找客户信息的方法(通过将 id 作为参数传递).

newStage would be the new window. The problem is, I can't find a way to tell the controller where to look for the customer's info (by passing the id as parameter).

有什么想法吗?

推荐答案

使用 MVC

这个答案的大部分内容都集中在将参数从调用类传递到控制器的直接调用上.

Most of this answer focuses on a direct call to pass a parameter from a calling class to the controller.

如果相反,您想要将调用者和控制器解耦,并使用更通用的架构,包括具有可设置和可监听属性的模型类来实现控制器间通信,请参阅以下基本概述:

If instead, you want to decouple the caller and controller and use a more general architecture involving a model class with settable and listenable properties to achieve inter-controller communication, see the following basic overview:

推荐方法

这个答案列举了将参数传递给 FXML 控制器的不同机制.

This answer enumerates different mechanisms for passing parameters to FXML controllers.

对于小型应用程序,我强烈建议将参数直接从调用者传递到控制器 - 它简单明了,不需要额外的框架.

For small applications I highly recommend passing parameters directly from the caller to the controller - it's simple, straightforward and requires no extra frameworks.

对于更大、更复杂的应用程序,如果您想使用依赖注入,值得研究一下Event Bus 应用程序中的机制.

For larger, more complicated applications, it would be worthwhile investigating if you want to use Dependency Injection or Event Bus mechanisms within your application.

直接从调用者向控制器传递参数

通过从 FXML 加载器实例中检索控制器并调用控制器上的方法以使用所需的数据值对其进行初始化,将自定义数据传递给 FXML 控制器.

Pass custom data to an FXML controller by retrieving the controller from the FXML loader instance and calling a method on the controller to initialize it with the required data values.

类似于以下代码:

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:

A new FXMLLoader is constructed as shown in the sample code i.e. new FXMLLoader(location). The location is a URL and you can generate such a URL from an FXML resource by:

new FXMLLoader(getClass().getResource("sample.fxml"));

注意不要在 FXMLLoader 上使用静态加载函数,否则您将无法从加载器实例中获取控制器.

FXMLLoader 实例本身从不了解域对象.您不会直接将特定于应用程序的域对象传递到 FXMLLoader 构造函数中,而是:

FXMLLoader instances themselves never know anything about domain objects. You do not directly pass application specific domain objects into the FXMLLoader constructor, instead you:

  1. 在指定位置基于 fxml 标记构建 FXMLLoader
  2. 从 FXMLLoader 实例获取控制器.
  3. 调用检索到的控制器上的方法,为控制器提供对域对象的引用.

此博客(由另一位作者撰写)提供了另一种但类似的示例.

This blog (by another writer) provides an alternate, but similar, example.

在 FXMLLoader 上设置控制器

CustomerDialogController dialogController = 
    new CustomerDialogController(param1, param2);

FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
        "customerDialog.fxml"
    )
);
loader.setController(dialogController);

Pane mainPane = loader.load();

您可以在代码中构造一个新的控制器,将您想要的任何参数从您的调用者传递到控制器构造函数中.构建控制器后,您可以在调用 load() instance 方法之前在 FXMLLoader 实例上设置它.

You can construct a new controller in code, passing any parameters you want from your caller into the controller constructor. Once you have constructed a controller, you can set it on an FXMLLoader instance before you invoke the load() instance method.

要在加载器上设置控制器(在 JavaFX 2.x 中),您也不能在 fxml 文件中定义 fx:controller 属性.

由于 FXML 中 fx:controller 定义的限制,我个人更喜欢从 FXMLLoader 获取控制器,而不是将控制器设置到 FXMLLoader.

Due to the limitation on the fx:controller definition in FXML, I personally prefer getting the controller from the FXMLLoader rather than setting the controller into the FXMLLoader.

让控制器从外部静态方法中检索参数

此方法以 Sergey 对 Javafx 2.0 How-to Application.getParameters() in a Controller.java 文件.

This method is exemplified by Sergey's answer to Javafx 2.0 How-to Application.getParameters() in a Controller.java file.

使用依赖注入

FXMLLoader 支持依赖注入系统,如 Guice、Spring 或 Java EE CDI,允许您在 FXMLLoader 上设置自定义控制器工厂.这提供了一个回调,您可以使用它来创建控制器实例,其中依赖值由各自的依赖注入系统注入.

FXMLLoader supports dependency injection systems like Guice, Spring or Java EE CDI by allowing you to set a custom controller factory on the FXMLLoader. This provides a callback that you can use to create the controller instance with dependent values injected by the respective dependency injection system.

以下回答中提供了 JavaFX 应用程序和控制器依赖注入与 Spring 的示例:

An example of JavaFX application and controller dependency injection with Spring is provided in the answer to:

afterburner.fx 框架是一个非常好的、干净的依赖注入方法的示例使用它的示例 air-hacks 应用程序.afterburner.fx 依赖于 JEE6 javax.inject 执行依赖注入.

A really nice, clean dependency injection approach is exemplified by the afterburner.fx framework with a sample air-hacks application that uses it. afterburner.fx relies on JEE6 javax.inject to perform the dependency injection.

使用事件总线

最初的 FXML 规范创建者和实现者 Greg Brown 经常建议考虑使用事件总线,例如 Guava EventBus,用于 FXML 实例化控制器和其他应用逻辑之间的通信.

Greg Brown, the original FXML specification creator and implementor, often suggests considering use of an event bus, such as the Guava EventBus, for communication between FXML instantiated controllers and other application logic.

EventBus 是一个简单但功能强大的发布/订阅 API,带有注释,允许 POJO 在 JVM 中的任何位置相互通信,而无需相互引用.

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.

后续问答

关于第一种方法,你为什么要返回 Stage?该方法也可以是无效的,因为您已经给出了命令 show();就在回归阶段之前;.你如何通过返回 Stage 来计划使用

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 扩展 Stage.封装 FXML、控制器和模型数据的自定义对话框的面向对象接口的完整示例超出了本答案的范围,但对于任何倾向于创建一个的人来说,这可能是一篇有价值的博文.

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.

由名为 @dzim

Spring Boot 依赖注入示例

关于如何去做的问题Spring Boot 方式",有一个关于 JavaFX 2 的讨论,我在所附的永久链接中回答了这个问题.该方法仍然有效并于 2016 年 3 月在 Spring Boot v1.3.3.RELEASE 上进行了测试:https://stackoverflow.com/a/36310391/1281217

The question of how to do it "The Spring Boot Way", there was a discussion about JavaFX 2, which I anserwered in the attached permalink. The approach is still valid and tested in March 2016, on Spring Boot v1.3.3.RELEASE: https://stackoverflow.com/a/36310391/1281217

有时,您可能希望将结果传回给调用者,在这种情况下,您可以查看相关问题的答案:

Sometimes, you might want to pass results back to the caller, in which case you can check out the answer to the related question:

这篇关于传递参数 JavaFX FXML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆