简体   繁体   English

OSGi包中的JavaFX样式表

[英]JavaFX stylesheets inside OSGi bundle

I've placed "styles.css" in the root of my bundle, and now trying to figure out how to link it in code. 我已将“styles.css”放在我的包的根目录中,现在试图弄清楚如何在代码中链接它。 The problem is that @.getStylesheets().add(_) takes a String and not URL, so all approaches I know are failing here: 问题是@ .getStylesheets()。add(_)接受一个String而不是URL,所以我知道的所有方法都失败了:

Take 1: 拿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.

Take 2: 拿2:

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

NullPointerException

Take 3: 拿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

Take 4: 拿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

I'm using Felix-4.2.1 , Java-8 (build 1.8.0-ea-b115) , JavaFX-8 (8.0.0-ea-b115) . 我使用的是Felix-4.2.1Java-8(build 1.8.0-ea-b115)JavaFX-8(8.0.0-ea-b115)

The reason why this doesn't work is explained here: javafx jira RT-14177 . 这不起作用的原因在这里解释: javafx jira RT-14177 Since you cannot use the "ExternalForm" of a ressource, I copied it in a temp file by reading the input stream directly. 由于您无法使用资源的“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());

I really hope this helps you out. 我真的希望这会帮助你。

Jonathan 乔纳森

  • Make sure you're using the Classloader of a class which has access to the bundle containing the css file 确保您使用的类的类加载器可以访问包含css文件的包
  • If you're using a relative path, make sure that css is located relative to that class' package 如果您使用的是相对路径,请确保css相对于该类的包位置

Here is a sample how I've loaded a css file in Drombler FX ( Drombler FX is a modular Rich Client Platform for JavaFX based on OSGi and Maven (POM-first) ): 下面是我在Drombler FX中加载css文件的示例Drombler FX是基于OSGi和Maven的JavaFX模块化富客户端平台(POM优先) ):

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 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

Here: the Stylesheets class is in the same bundle as the css file. 这里:Stylesheets类与css文件位于同一个包中。

I recently ran in the same error/troubles as the original poster of this question and I managed to solve it without making any changes to the css/fxml or extracting it to a temp file. 我最近遇到了与此问题的原始海报相同的错误/问题,我设法解决了它,而没有对css / fxml进行任何更改或将其解压缩到临时文件。 I'm posting it here as I did not find any good answer online: 我在这里发帖,因为我没有在网上找到任何好的答案:

In my case the setup was: 在我的情况下,设置是:

Bundle0: Bundle0:

  • someview.fxml with a relative path reference to a css file someview.fxml,带有对css文件的相对路径引用
  • somestyle.css with relative path references to images somestyle.css具有对图像的相对路径引用
  • someimage.png someimage.png
  • Resourceloader.java (returns URL objects from css and fxml files) Resourceloader.java(从css和fxml文件返回URL对象)

Bundle1: Bundle1:

  • basic javafx files to load the fxml with an fxml loader from bundle0. 使用bundle0中的fxml加载器加载fxml的基本javafx文件。

The problem: 问题:

All css and css referenced images seemed to be ignored by the fxml, even though I set the classloader on the fxml loader. 尽管我在fxml加载器上设置了类加载器,但fxml似乎忽略了所有css和css引用的图像。 It only worked if I used an absolute file path for the css and the images referenced in the css. 它只有在我使用css的绝对文件路径和css中引用的图像时才有效。 This is not what I want. 这不是我想要的。

The solution: 解决方案:

There are 2 bugs/design issues in JavaFX that prohibit this setup from working with OSGi. JavaFX中存在2个错误/设计问题,禁止此设置与OSGi一起使用。

  • Loading the css from fxml 从fxml加载css
  • referencing images from a css 引用来自CSS的图像

To fix the the first problem, you have to disable binary css file in javafx by setting the system property binary.css to false. 要解决第一个问题,您必须通过将系统属性binary.css设置为false来禁用javafx中的二进制css文件。 There is a bug in javafx (maybe it's already fixed?) where javafx tries to be smart and tries to find the bss file, even though you say css. javafx中有一个错误(可能它已经修复了吗?),即使你说css,javafx试图变聪明并试图找到bss文件。 It flips because OSGi resource URLs have a 'bundle://' schema where it expects no schema. 它会翻转,因为OSGi资源URL有一个'bundle://'架构,它不需要架构。 Solution: 解:

  • -Dbinary.css=false -Dbinary.css = FALSE

To fix the second problem, you have to set the thread context classloader to the classloader of the bundle where the css images are located and then restore the thread context classloader. 要解决第二个问题,您必须将线程上下文类加载器设置为css映像所在的包的类加载器,然后还原线程上下文类加载器。 The trick is to do this each time the css is interpreted by JavaFX, which is not always when you expect it to be... 诀窍是每次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);
    }

Unfortunately this is the best solution I could come up with. 不幸的是,这是我能想到的最好的解决方案。 JavaFX was not made with class loader or dependency injection in mind, even though just about every corporate application uses those functionalities in some form. 尽管几乎每个企业应用程序都以某种形式使用这些功能,但JavaFX并未考虑类加载器或依赖注入。 :( :(

//edit It looks like you don't need to set the thread context classloader to access the images from the css! //编辑看起来你不需要设置线程上下文类加载器来访问来自css的图像!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM