如何引用资源文件夹中的 javafx fxml 文件?

Posted

技术标签:

【中文标题】如何引用资源文件夹中的 javafx fxml 文件?【英文标题】:How to reference javafx fxml files in resource folder? 【发布时间】:2013-11-05 07:58:36 【问题描述】:

我正在创建一个 javafx GUI 应用程序,我的项目是一个 maven 配置项目。我希望能够在我的控制器中像这样引用我的 fxml 文件:

FXMLLoader.load(getClass().getResource("main.fxml"); 

我的 main.fxml 文件位于 src/main/resources 文件夹中,而我的控制器位于 src/main/java 文件夹中。我该怎么做呢?我的 src/main/resources 文件夹位于构建路径中,我可以从 src/main/java 文件夹中的类调用 src/main/resources 文件夹中的 .properties 文件。

编辑

我尝试将fxml文件放在主资源文件夹的对应目录中:

但我仍然遇到错误。

【问题讨论】:

【参考方案1】:

通用资源查找信息

这个答案讨论了 FXML 位置查找,它实际上只是 Java 中通用资源查找任务的一个子集。调用程序将资源位置作为输入传递给 FXMLLoader,因此资源查找本身是调用应用程序代码的一部分,而不是 FXMLLoader。

有关 Java/JavaFX 应用程序的通用资源信息(包括推荐的故障排除步骤)的全面介绍,请参阅:

How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?

Eden 编码资源指南也很有用:

Where to put resource files in JavaFX

示例用法

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/main.fxml"));
Parent content = loader.load(); 

位置分辨率选项

    把你所有的 fxml 放到 src/main/resources 目录下。

    loader.setLocation(getClass().getResource("/main.fxml"));
    

    把你所有的 fxml 放到一个 src/main/resources/fxml 目录下。

    loader.setLocation(getClass().getResource("/fxml/main.fxml"));
    

    将fxml放在对应的资源目录中;例如src/main/resources/com/mycompany/myapp.

    loader.setLocation(getClass().getResource("main.fxml")); 
    

最后一个选项假定您从中加载 fxml 的类位于相应 Java 源层次结构中的相同相对位置。例如,您可以从源代码com/mycompany/myapp/Main.java 调用最后一个加载命令。

FXMLLoader 使用建议

    通过new FXMLLoader() 实例化一个 FXMLLoader 而不是使用 static methods on the FXMLLoader。

    静态方法 当你想get values 时变得混乱(比如实例化 控制器)从加载器中取出。

    Set the location 在实例化的 FXMLLoader 上并调用 load() 而不是使用从流中加载 load(stream).

    在加载器上设置基于 URL 的位置允许解析 在 fxml 和 css 文件中加载的相关资源。相对的 资源不会为基于流的构造函数解析。

    要基于类派生位置,请使用 getClass().getResource(),因为它是基于 URL 的,而不是 getClass().getResourceAsStream() 是基于流的。

IDE 和构建设置

确保您的 IDE 或构建工具正在将 fxml 文件从资源目录复制到构建输出目录。要了解 Intellij 设置,请参阅:How to convert a normal java project in intellij into a JavaFx project。

关于 Java Jigsaw 模块化应用程序的说明

见:

How to access resource using class loader in Java 9

具体不要写:

ComboBoxStyling.class.getClassLoader()
    .getResource("/css/styleclass.css");

改为写:

ComboBoxStyling.class
    .getResource("/css/styleclass.css"); 

也就是说,直接从类中获取资源,而不是从类加载器中获取。如果您从类加载器而不是类中获取资源,那么基于模块配置的查找会有额外的限制。这些限制可能很难理解,如果需要,请参阅 ClassClassLoader getResource 方法的文档以获取信息。

【讨论】:

您仍在使用示例中的静态方法。您需要调用 getResourceAsStream 而不是 getResource 感谢 Felix,修复并澄清了答案。 3 年和 28 次投票,之前没有人在原始答案中指出这个异常;-) 一直以来,它都失败了,因为我没有将/ 放在开始文件夹之前。 IE。 getClass().getResource("fxml/main.fxml"). NetBeans 用户快速注意事项,您可以通过右键单击项目目录 > 属性 > 选择“源” > 选择要添加到源的文件夹 > 添加文件夹来将现有文件夹添加到 src。因此,如果您已经有一个包含您要引用的 fxml 的文件夹,您只需添加该文件夹并使用它们的相对路径调用 fxml 文件。【参考方案2】:

在您操作系统的文件资源管理器中打开您的资源文件夹。在这里,您将看到您创建了一个“dominion.application”文件夹,而不是“dominion”文件夹内的“application”文件夹。因此,“MainController”类与 fxml 文件放在不同的包中。

【讨论】:

【参考方案3】:

您正在使用FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource("main.fxml") ); 加载您的 main.fxml。这需要将 main.fxml 和 java 类加载到相同的目录/路径中。 如果要从与加载它的 java 类不同的路径/位置加载 fxml 文件,则需要使用相对路径。 正如上面提到的@jewelsea,您可以在 main.fxml 之前使用 / 字符使用相对路径。 因此,在您的情况下,使其为您工作的代码是

FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource("/main.fxml") );

【讨论】:

其实这是对问题的简单回答,仔细想想也是有道理的。该路径相对于调用 FXMLLoader() 的源文件。

以上是关于如何引用资源文件夹中的 javafx fxml 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何确定我的 JavaFX 应用程序所需的 FXML 文件、CSS 文件、图像和其他资源的正确路径?

我如何将javax.swing.ImageIcon绘制为JavaFX .fxml呈现的用户界面?

如何使用不同的 fxml 文件创建多个 javafx 控制器?

JavaFX 动态地将标签添加到窗格,在 fxml 文件中定义

无法在 JavaFX 中加载 FXML 文件

如何使用 FXML 在 JavaFX 中创建 CheckBoxTreeItem