【问题标题】:Can I automatically generate controller classes from FXML?我可以从 FXML 自动生成控制器类吗?
【发布时间】:2014-02-05 10:52:51
【问题描述】:

据我了解,当使用 FXML 描述 Java FX 场景时,控制器类是手动编写的,然后可以从.fxml 文件。当使用FXMLLoader 加载场景时,成员变量被设置为相应的场景元素,方法自动连接到相应的事件。这可行,但非常麻烦,因为需要在两个地方进行更改,并且任何错误只会在运行时出现。

我见过其他 GUI 框架,它们允许您从场景描述生成控制器作为一个抽象类,需要实现该抽象类来访问场景元素和处理事件。我的意思的一个例子:

我将创建以下 .fxml 文件(例如,使用 JavaFX 场景构建器):

<AnchorPane ... >
  <children>
     <Button fx:id="button" ... text="Button" onAction="#buttonPressed" />
  </children>
</AnchorPane>

在我的构建过程中,将创建以下.java 文件(例如,使用 Maven 插件):

abstract class TestController {
    protected final Parent root;
    protected final Button button;

    {
        // Load test.fxml file
        // Assign scene elements to root and button
        // Attach event handler to the button that calls buttonClicked()
    }

    protected abstract void buttonClicked(ActionEvent event);
}

然后,我可能会多次创建该控制器的具体实现:

final class TestControllerImpl extends TestController {
    TestControllerImpl(String buttonLabel) {
        button.setText(buttonLabel);
    }

    @Override
    protected void buttonClicked(ActionEvent event) {
        button.setText("I've been clicked! What a great day!");
    }
}

是否有一个目标是这样做的项目?或者这种方法应用于 FXML 是否有问题?

我看到这种方法有以下好处:

  • 自动生成控制器的成员变量和方法的声明。
  • 所有成员变量都是 finalprotected 而不是 non-finalpublic 或注释。
  • 方法也一样,它们是 protected 而不是 public 或注释。
  • 未实现方法或拼写错误名称将导致编译器错误。
  • 场景的编程设置可以在构造函数中完成,而不是在 initialize() 方法中完成,因为构造函数将在场景加载并将其元素分配给成员变量之后运行。李>

【问题讨论】:

  • 只是出于好奇,你用过javafx scene builder的自动控制器示例吗?
  • @ItachiUchiha 我有,虽然它确实减少了一点点创建控制器类的工作,但它并没有解决我想避免的任何问题。此外,它仅在最初创建控制器时有帮助,而在使用现有控制器修改视图时没有帮助。

标签: javafx code-generation fxml


【解决方案1】:

现在 SceneBuilder、NetBeans 和 Eclipse 都支持此功能。请注意,这在 NetBeans 和 SceneBuilder 中是开箱即用的,但在 Eclipse 中,您首先需要 e(fx)clipse 插件。

场景构建器: 在编辑器中打开 FXML 文件,进入菜单选择“查看”和“显示示例控制器骨架”。

日食: 打开 fxml 文件,使内容显示在代码编辑窗格中(您应该将 fxml 视为纯文本 xml,在 Eclipse 中具有语法高亮显示,而不是在 SceneBuilder 中以可视方式呈现)。右键单击Eclipse中的代码并选择“代码”,然后选择“生成控制器”。

NetBeans: 在 NetBeans 中更简单,在项目资源管理器中右键单击 fxml 文件并选择“制作控制器”。

【讨论】:

  • +1 顺便说一句,只是一个更新。在 Eclipse Oxygen 中,它将是右键单击代码 -> 源 -> 生成控制器
  • @user3437460。我很高兴你这么说,就像在 Eclipse Photon 中找不到一样。可惜它说,“不支持更新现有的控制器!”也许有一天,拼写更正了!!
  • 在 eclipse 2020-09 上,我是否必须在按下 Generate Controller 之前创建一个单独的控制器类,或者如果你有一个控制器类,它会自动创建一个吗?我实际上尝试了上述解决方案,但除非我创建了一个控制器类,否则它不会生成控制器类。在 IntelliJ v2020 及更高版本上,如果您还没有控制器类,它将要求用户创建一个。
【解决方案2】:

2020 年 11 月更新

这个答案现在已经过时了。

正如最近的各种答案所指出的,现在有多种不同的工具可用于从 FXML 文档自动生成 FXML 控制器类。其中许多是针对现有开发工具(例如 SceneBuilder、Idea、Eclipse 或 NetBeans)的扩展、功能或插件。

我建议感兴趣的读者查看这个答案和这个问题的其他答案,然后查看他们的个人用例和工具集链,并从可用选项中选择最适合他们的解决方案。


据我所知,没有什么能完全符合您在问题中提出的建议。

随着时间的推移,这个答案可能最终会过时。

替代技术

JRuby 使用稍微不同的方法实现了您概述的大部分好处 - 它使用 jRuby 的动态编程魔法在运行时动态地从 FXML 自动创建 Ruby 类成员。

Tom Schindl 编写了一个从 FXML 生成 Java 代码的工具。在此答案中列出的方法中,Tom 的工具似乎最接近您的问题。

SceneBuilder 骨架

SceneBuilder View | Show Sample Controller Skeleton 功能中提供了来自 FXML 的类似 Java 代码生成器,此 blog post 对此进行了描述。当我使用 SceneBuilder 时,我一直都在使用这个功能,并尽量让我的控制器非常轻便,因此它们几乎都是从 SceneBuilder 骨架功能自动生成的代码。

这有点烦人,因为它无法将生成的代码与手写代码完全分离,所以当你更新 FXML 并想要生成一个新的骨架并复制和粘贴它时,你需要小心覆盖现有控制器的某些部分(另外,这是一个容易出错的手动操作,需要一些开发人员时间)。

Source code for SceneBuilder 如果您想看看它是如何工作的,可以使用它。

潜在的构建工具插件

这样的代码生成功能可能是对 JavaFX 生态系统中一些现有构建工具的有价值的补充,例如 JavaFX Maven pluginJavaFX Gradle plugin(或它自己的单独插件)。

未来发展

我相信 Oracle 还在为未来的 JavaFX 版本(Java 8 之后)开发 FXML 的功能扩展,该版本将 FXML 直接编译为 Java 字节码(类文件),绕过 Java 源代码步骤。这种功能可能会实现您列出的大部分好处。

【讨论】:

    【解决方案3】:

    NetBeans 版本 8 可以实现。

    打开 FXML ,进入 Source 并点击 generate controller。

    编辑:现在可以在任何 IDE 中完成,Eclipse 需要一个插件思想。

    【讨论】:

    • 我正在寻找构建系统自动化的东西,例如使用 Maven 插件。
    【解决方案4】:

    对于 Intellij Idea IDE 用户,FXMLManager 来拯救。见插件homepage

    “当在 .fxml 文件上单击鼠标右键时,会出现新的菜单项“从 FXML 更新控制器”。 点击此项将修改FXML Java Controller:

    • 删除 FXML 及其 getter/setter 中缺少的所有 @FXML 字段
    • 添加 Controller 中缺少的所有 @FXML 字段
    • @弃用 FXML 中缺少的所有 ActionEvent 方法
    • 创建 Controller 中缺少的所有 ActionEvent 方法"

    【讨论】:

      【解决方案5】:

      据我所知,netbeans 中存在两种解决方案。

      首先,netbeans 的内部功能“Make Controller”,您可以在 fxml 文档上单击鼠标右键查看。它将生成与 FXMLLoader 一起使用的控制器类。控制器的 java 文件名应在 fxml 文档中指明。 (左面板 -> 控制器 -> 控制器类)

      Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
      

      二、netbeans的插件“FXML 2 JAVA Converter”,可以从菜单(Tool -> Plugin -> Available Plugin -> FXML 2 JAVA Converter)安装。您可以在 fxml 文档上单击鼠标右键看到“生成抽象类”菜单项。它将从 fxml 文档生成源代码,您可以将其用作抽象类,而无需像普通 JavaFX 项目而不是 JavaFXML 项目那样使用 FXMLLoader。

      【讨论】:

      • 嗨,我已经安装了插件,我可以在插件窗口的“已安装”选项卡中看到它,但是当我右键单击我的 fxml 文件时,我没有看到“生成抽象类”菜单项.
      【解决方案6】:

      现在你可以很容易地用 eclipse 做这些简单的步骤:

      1. 转到您要为其创建控制器的 fxml 文件
      2. 右键单击并单击源
      3. 点击生成控制器

      Click here to see the Picture of How to do it.

      【讨论】:

      • 感谢哈马德!!!有用!但是你必须指定你应该在fxml之前打开,然后直接在代码上单击右键(不是在包资源管理器中),然后选择Source -> generate controller。
      • 是的!正是这样
      • 这个解决方案是自动创建控制器类还是我们应该单独创建控制器类并在点击Generate Controller之前绑定FXML?
      【解决方案7】:

      如果您使用的是 IntelliJ ide,您可能需要尝试FXML Helper 插件。

      首先,从 File | 安装插件设置... |插件。安装完成后重启ide,现在右击.fxml文件,选择FXML Helper菜单。仅此而已。

      【讨论】:

        【解决方案8】:

        @Feuermurmel
        不,没有任何方法可以为特定的 .fxml 文件自动生成控制器类。
        您应该在场景构建器中使用注释@fxml 和 set(bind) 定义动态声明变量和方法。

        【讨论】:

        • 这是什么意思?愿意说明一些示例照片吗?
        猜你喜欢
        • 2016-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-18
        相关资源
        最近更新 更多