【问题标题】:Locating CSS for loading from FXML定位 CSS 以从 FXML 加载
【发布时间】:2021-05-16 16:50:15
【问题描述】:

JDK 11、JavaFX 15。

尽管How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application? 的回答很好,这仍然让我感到困扰。它不解决加载相关资源的问题。

我有一个加载引用 CSS 文件的 FXML 文件的简单示例。

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" 
            styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" 
            xmlns="http://javafx.com/javafx/11.0.1">
    <stylesheets>
        <URL value="@/styles/root.css" />
    </stylesheets>
</AnchorPane>

这是 pkg/App.java 类:

package pkg;

public class App extends Application {

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader loader = new FXMLLoader(App.class.getResource("root.fxml"));       
        scene = new Scene(loader.load());
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

这是root.css 文件:

.mainFxmlClass {

}

这是 jar 布局(消除 maven 样板、模块信息、清单)。

pkg/App.class
pkg/root.fxml
pkg/styles/root.css
styles/root.css

我得到的相关异常是:

Caused by: javafx.fxml.LoadException: Invalid resource: /styles/root.css not found on the classpath

根据Introduction to FXML,在位置分辨率下,它说:

作为字符串,XML 属性不能原生地表示类型化的位置 URL 等信息。但是,通常需要指定 标记中的此类位置;例如,图像的来源 资源。位置解析运算符(由“@”表示 属性值的前缀)用于指定一个属性 value 应被视为相对于当前文件的位置 而不是一个简单的字符串。

异常指定“/styles/root.css”,这是一个绝对路径。从 JAR 布局中可以看出,我有一个 /styles/root.css。但是文档说“相对于当前文件”。

假设“当前文件”是/pkg/root.fxml,那么/pkg/styles/root.css(应该)相对于/pkg/root.fxml(或者是/pkg/App.class?),但它也找不到这个。

如果我注释掉 stylesheets 元素,文件加载正常。

那么,我应该将root.css 文件放在哪里?

【问题讨论】:

  • 由于错误消息说无法找到/styles/root.css,我的猜测是前导斜杠会导致问题。如果你改用"@styles/root.css" 会怎样?
  • 尝试@../styles/root.css,对于同一个文件夹,使用 Slaw 的答案。
  • 您是否验证了 jar 文件的内容(例如,从命令行使用jar -tf)?还是您只是在源代码布局中展示您认为存在的内容?
  • @James_D 这是实际的 jar 文件(减去我认为不相关的内容)。

标签: css javafx


【解决方案1】:

要在 FXML 文件中引用 CSS 文件,您可以使用:

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" 
            styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" 
            xmlns="http://javafx.com/javafx/11.0.1">
    <stylesheets>
        <String fx:value="/styles/root.css" />
    </stylesheets>
</AnchorPane>

注意:

  1. 字符串不是 URL
  2. fx:值不是值
  3. 开头没有“@”
  4. 似乎只支持绝对路径

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" 
            styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" 
            xmlns="http://javafx.com/javafx/11.0.1" 
            stylesheets="@/styles/root.css" />
</AnchorPane>

注意:

  1. 属性不是嵌套元素
  2. 逗号分隔的样式表列表
  3. 此处的样式表 URL 必须以“@”开头
  4. 支持绝对和相对 URL

接下来是配置正确的位置,这应该由您正在使用的构造函数设置,因此应该没问题。

您可以找到完整的示例here

该示例使用Drombler CommonsFXMLLoaders 实用程序类支持的约定优于配置方法。

如果您将root.fxml 重命名为App.fxml,则对于您的示例,它可能如下所示:

    scene = new Scene(FXMLLoaders.load(App.class));

它还将查找App.properties 文件(和特定于语言环境的派生;必须在同一个包中),如果您的 FXML 文件中有 i18n 文本,这可能会很有用。 此外,它将设置正确的ClassLoader 和位置并抛出RuntimeExceptions 而不是检查异常,因为用户无论如何都无法更改任何内容。

您可以通过添加以下依赖项来使用此实用程序类:

<dependency>
  <groupId>org.drombler.commons</groupId>
  <artifactId>drombler-commons-fx-core</artifactId>
  <version>1.0</version>
</dependency>

图书馆是Open Source

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2019-02-22
    • 2017-08-05
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多