我可以从FXML自动生成控制器类吗? [英] Can I automatically generate controller classes from FXML?

查看:176
本文介绍了我可以从FXML自动生成控制器类吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As I understand it, when using FXML to describe a Java FX scene, the controller class is written manually and it's member variables and methods can then be referenced from the .fxml file. When loading the scene using the FXMLLoader, member variables are set to the corresponding scene elements and methods are wired up to the corresponding events automatically. This works but is very cumbersome as changes need to be done in two places and any mistakes will only show up at runtime.

我看到了其他允许您使用的GUI框架而是根据场景描述将控制器生成为抽象类,该类需要实现以访问场景元素并处理事件。我的意思的示例:

I've seen other GUI frameworks that allow you to instead generate the controller from a scene description as an abstract class which needs to be implemented to access the scene elements and handle the events. An example of what I mean:

我将创建以下 .fxml 文件(例如,使用 JavaFX Scene Builder ):

I would create the following .fxml file (e.g. using the JavaFX Scene Builder):

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

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

Somewhere in my build process, the following .java file would be created (e.g. using a Maven plugin):

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);
}

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

I could then, possibly multiple times, create a concrete implementation of that controller:

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 是否存在问题?

Is there a project with the goal to do this? Or is there a problem with this approach applied to FXML?

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

I see the following benefits from this approach:


  • 会自动生成成员变量的声明和控制器方法。

  • 所有成员变量都是 final 受保护的而不是 non-final public 或已注释。

  • 方法相同,它们受保护而不是 public 或带有注释。

  • 不实现方法或拼写错误的名称将导致编译器错误

  • 可以在构造函数中完成场景的程序设置,而不是 initialize()方法,因为构造函数将运行之后,场景已加载,其元素已分配给成员变量。

  • Declarations for member variables and methods for the controller are automatically generated.
  • All member variables are final and protected instead of non-final and either public or annotated.
  • The same for methods, they are protected instead of either public or annotated.
  • Not implementing a method or misspelling it's name will lead to a compiler error.
  • Programmatic setup of the scene can be done in the constructor instead of an initialize() method because the constructor will run after the scene has been loaded and its elements assigned to the member variables.

推荐答案

据我所知,没有什么可以完全满足您在问题中的建议。

There is nothing I know that does exactly what you propose in your question.

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

Likely this answer will probably end up pretty outdated over time.

替代技术

JRuby 通过使用jRuby的动态编程魔术功能,可以在运行时动态地从FXML自动创建Ruby类成员。

JRuby achieves most of your outlined benefits using a slightly different approach - it uses jRuby's dynamic programming magic to automatically create Ruby class members from the FXML dynamically a runtime.

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

Tom Schindl wrote a tool which generates Java code from FXML. Of the approaches listed in this answer, Tom's tool seems closest to your question.

SceneBuilder骨架

SceneBuilder 中提供了类似的FXML Java代码生成器。显示示例控制器骨架功能,此博客文章。当我使用SceneBuilder时,我一直都在使用此功能,并尝试使控制器保持真正的明亮状态,因此它们几乎都是由SceneBuilder骨架功能自动生成的代码。

A similar Java code generator from FXML is available in SceneBuilder View | Show Sample Controller Skeleton feature, which is described in this blog post. When I use SceneBuilder, I use this feature all the time and try to keep my controllers really light so they are almost all auto generated code from the SceneBuilder skeleton feature.

这有点烦人,因为它不能将生成的代码与手写代码完全分开,因此在更新FXML时需要小心并希望生成一个新的骨架并将其复制并粘贴到现有Controller的各个部分上(另外,这是一个容易出错的手动操作,需要花费一些开发人员时间)。

It is slightly annoying though because it doesn't achieve a clean separation of generated code from hand written code, so you need to be careful when you do updates to the FXML and want to generate a new skeleton and copy and paste it over parts of your existing Controller (plus that is a slightly error prone manual operation that takes a little bit of developer time).

SceneBuilder的源代码是可用的,如果您想了解它是如何工作的。

Source code for SceneBuilder is available if you want to see how it works.

潜在的构建工具插件 strong>

这种代码生成功能可能为JavaFX生态系统中的某些现有构建工具(例如 JavaFX Maven插件 JavaFX Gradle插件(或单独使用的插件)。

Such a code generation feature might make a worthwhile addition to some of the existing build tools in the JavaFX ecosystem, such as the JavaFX Maven plugin or JavaFX Gradle plugin (or a separate plugin in it's own right).

未来发展

我相信Oracle还在为将来的JavaFX版本(Java 8之后)开发FXML的功能扩展,该功能将FXML直接编译为Java字节码(类文件),而绕开了Java源代码步骤。这种功能可能会实现您概述的大多数优点。

I believe that Oracle are also working on a feature extension for FXML for a future JavaFX release (post Java 8) which compiles FXML directly to Java byte code (class files), bypassing the Java source code step. This kind of feature would probably achieve most of your outlined benefits.

这篇关于我可以从FXML自动生成控制器类吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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