OSGi包中的JavaFX样式表

时间:2013-11-15 12:17:21

标签: java javafx osgi javafx-8 java-8

我已将“styles.css”放在我的包的根目录中,现在试图弄清楚如何在代码中链接它。问题是@ .getStylesheets()。add(_)接受一个String而不是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(版本1.8.0-ea-b115) JavaFX-8(8.0。 0-EA-B115)

4 个答案:

答案 0 :(得分:3)

这不起作用的原因在这里解释:javafx jira RT-14177。 由于您无法使用资源的“ExternalForm”,因此我通过直接读取输入流将其复制到临时文件中。

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

我真的希望这会帮助你。

乔纳森

答案 1 :(得分:2)

  • 确保您使用的类的类加载器可以访问包含css文件的包
  • 如果您正在使用相对路径,请确保css相对于该类位于'封装

以下是我在Drombler FXDrombler FX is a modular Rich Client Platform for JavaFX based on OSGi and Maven (POM-first))中加载css文件的示例:

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

此处:Stylesheets类与css文件位于同一个包中。

答案 2 :(得分:2)

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

在我的情况下,设置是:

Bundle0:

  • someview.fxml,其中包含对css文件的相对路径引用
  • somestyle.css,其中包含对图像的相对路径引用
  • someimage.png
  • Resourceloader.java(从css和fxml文件返回URL对象)

Bundle1:

  • 基本的javafx文件,用来自bundle0的fxml加载器加载fxml。

问题:

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

解决方案:

JavaFX中存在2个错误/设计问题,禁止此设置与OSGi一起使用。

  • 从fxml加载css
  • 引用来自css的图片

要解决第一个问题,您必须通过将系统属性binary.css设置为false来禁用javafx中的二进制css文件。 javafx中有一个错误(也许它已经修复了吗?),即使你说css,javafx试图变聪明并试图找到bss文件。它会翻转,因为OSGi资源网址有一个' bundle://'架构,它期望没有架构。解决方案:

  • -Dbinary.css =假

要解决第二个问题,您必须将线程上下文类加载器设置为css映像所在的bundle的类加载器,然后还原线程上下文类加载器。诀窍是每次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的图像!

答案 3 :(得分:0)

的getClass()。getClassloader()。的getResource()。toExternalForm()?