javafx - 传递参数JavaFX FXML

标签 javafx parameters dependency-injection parameter-passing fxml

如何将参数传递给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 InjectionEvent 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构造函数中,而是:
  • 基于fxml标记在指定位置构造FXMLLoader
  • 从FXMLLoader实例获取 Controller 。
  • 在检索到的 Controller 上调用方法,以为 Controller 提供对域对象的引用。

  • 该博客(由另一位作者撰写)提供了一个替代但相似的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)的示例:
  • Adding Spring Dependency Injection in JavaFX (JPA Repo, Service)

  • 一个非常好的,干净的依赖项注入(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 FXML Parameter passing from Controller A to B and back
  • 关于javafx - 传递参数JavaFX FXML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16744129/

    相关文章:

    ruby-on-rails - 如何将默认过滤器传递给Filterrific get

    python - 类属性与方法参数性能? Python

    dependency-injection - 如何开始使用 ASP.NET (5) Core 和 CaSTLe Windsor 进行依赖注入(inject)?

    c# - 在转换到新供应商期间,如何有效地将一个应用程序映射到两个数据库后端?

    TextArea 的 JavaFX CSS 样式不起作用

    c# - 将多个可选参数传递给 C# 函数

    JavaFX:线程 "JavaFX Application Thread"java.lang.RuntimeException 中出现异常:java.lang.reflect.InitationTargetException

    c# - 对用户控件的依赖注入(inject)

    java - 围绕自定义点旋转 javafx ImageView

    java - 检测打开我的 JavaFX 程序的文件