OSGi bundle中的 JavaFX 样式表



我已经将"styles.css"放在我的捆绑包的根目录中,现在试图弄清楚如何在代码中链接它。问题是@.getStylesheets().add(_)采用字符串而不是URL,因此我知道的所有方法在这里都失败了:

取 1:

scene.getStylesheets().add("styles.css");

Nov 15, 2013 2:04:47 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "styles.css" not found.

取 2:

scene.getStylesheets().add(this.getClass().getResource("styles.css").toExternalForm());

NullPointerException

取3:

scene.getStylesheets().add(this.getClass().getClassLoader().getResource("styles.css").toExternalForm());

Nov 15, 2013 2:27:31 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:1/styles.css

取4:

scene.getStylesheets().add(myBundle.getEntry("styles.css").toExternalForm());

Nov 15, 2013 1:31:35 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:0/styles.css

我正在使用Felix-4.2.1,Java-8(build 1.8.0-ea-b115),JavaFX-8(8.0.0-ea-b115)。

这里解释了为什么这不起作用:javafx jira RT-14177。由于您不能使用资源源的"外部表单",因此我通过直接读取输入流将其复制到临时文件中。

        InputStream inputStream = MainApp.class.getResourceAsStream("/styles/styles.css");
        File tempStyleSheetDest = File.createTempFile("javafx_stylesheet", "");
        tempStyleSheetDest.deleteOnExit();
        Files.copy(inputStream, tempStyleSheetDest.toPath(), StandardCopyOption.REPLACE_EXISTING);
        scene.getStylesheets().add(tempStyleSheetDest.toURI().toString());

我真的希望这对你有所帮助。

乔纳森

我最近遇到了与此问题的原始海报相同的错误/麻烦,我设法解决了它,而无需对 css/fxml 进行任何更改或将其提取到临时文件。我在这里发布它,因为我在网上没有找到任何好的答案:

就我而言,设置是:

捆绑包0:

  • someview.fxml,具有对 CSS 文件的相对路径引用
  • somestyle.css具有对图像的相对路径引用
  • 某图像.png
  • 资源加载器.java(从 css 和 fxml 文件返回 URL 对象)

捆绑包1:

  • 基本 JavaFX 文件,用于从 bundle0 使用 fxml 加载器加载 fxml。

问题:

所有 css 和 css 引用的图像似乎都被 fxml 忽略了,即使我在 fxml 加载器上设置了类加载器。仅当我对 css 和 css 中引用的图像使用绝对文件路径时,它才有效。这不是我想要的。

解决方案:

JavaFX 中有 2 个错误/设计问题阻止此设置与 OSGi 一起使用。

  • 从 fxml 加载 css
  • 从 CSS 引用图像

要解决第一个问题,您必须通过将系统属性 binary.css 设置为 false 来禁用 javafx 中的二进制 css 文件。javafx中有一个错误(也许它已经修复了?),javafx试图变得聪明并试图找到bss文件,即使你说css。它翻转是因为OSGi资源URL具有"bundle://"模式,它不需要任何模式。溶液:

  • -Dbinary.css=false

要解决第二个问题,您必须将线程上下文类加载器设置为css图像所在的捆绑包的类加载器,然后恢复线程上下文类加载器。诀窍是每次 JavaFX 解释 css 时都这样做,这并不总是在您期望它的时候......

ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        try {
            final ClassLoader resourcesClassLoader = Resourceloader.class.getClassLoader();
        //needed for css
        Thread.currentThread().setContextClassLoader(resourcesClassLoader);
        this.primaryStage.show();
    } finally {
        Thread.currentThread().setContextClassLoader(tccl);
    }

不幸的是,这是我能想到的最好的解决方案。JavaFX在开发时并没有考虑到类加载器或依赖注入,尽管几乎每个企业应用程序都以某种形式使用这些功能。:(

//编辑看起来您不需要设置线程上下文类加载器即可从 css 访问图像!

    确保您使用的是类的类加载器,该
  • 类可以访问包含 css 文件的捆绑包
  • 如果您使用的是相对路径,请确保 css 相对于该类的包定位

以下是我如何在Drombler FX中加载css文件的示例(Drombler FX是基于OSGi和Maven(POM优先)的JavaFX模块化富客户端平台):

http://sourceforge.net/p/drombler/drombler-fx/ci/default/tree/drombler-fx-core-docking/src/main/java/org/drombler/fx/core/docking/impl/skin/Stylesheets.java

这里:样式表类与 css 文件位于同一捆绑包中。

getClass().

getClassloader().getResource().toExternalForm()?

最新更新