由于com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged,JavaFx无法加载@ font-face字体

时间:2015-12-02 06:25:40

标签: java javafx java-8 javafx-2 javafx-8

我已经问了一个类似的问题here但似乎不清楚,因为我在项目中有很多代码而无法在此发布所以标记为重复。

正因为如此,我决定创建一个新项目,其中只有一个标签,以使代码小而干净,并消除其他潜在嫌疑人我得到的错误。

所以这是我的 Java源代码

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();

        Label label = new Label("Sample Label");
        label.setId("sampleLabel");
        root.getChildren().add(label);

        Scene scene = new Scene(root, 300, 275);
        scene.getStylesheets().add(getClass().getResource("applicationStyles.css").toExternalForm());
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

这是我的 css文件

/**/
@font-face {
    font-family:'Roboto';
    src:url("Roboto-Thin.ttf");
}
#sampleLabel{
    -fx-font-family: Roboto ;
}

这是我在Intellij Idea中遇到的错误

Dec 02, 2015 9:16:34 AM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load @font-face font [file:/C:/Users/UserName/Desktop/Java8%20projects/TeamViewer/out/production/TeamViewer/sample/Roboto-Thin.ttf]
  

所有项目文件都在一个包中,字体文件也出现在out> production> TeamViewer>示例> Roboto-Thin.ttf中。我也从jdk-8u65升级到jdk-8u66

谢谢,非常感谢任何帮助。

5 个答案:

答案 0 :(得分:2)

我找到了可能的原因和解决方法: 在引擎盖下,css-loader使用函数Font.loadFont在CSS中加载font-face。 如果Font.loadFont失败,null只会返回%20,这会给出“警告”。

似乎这个函数不能与(require '[clojure.java.io :as cio]) (require '[clojure.string :as s]) (-> "fonts/SourceCodePro-Regular.ttf" cio/resource str (s/replace "%20" " ") (javafx.scene.text.Font/loadFont 10.)) 它的路径/ url-string一起使用。 因此,您需要解析路径,然后用空格替换它。 这意味着您必须使用代码而不是CSS(现在)加载字体。

在Clojure中,我的解决方案看起来像这样:

// This you should know
var certPath = @"path-to-file.pfx";
var certPass = @"password-goes-here";

// Create a collection object and populate it using the PFX file
X509Certificate2Collection collection = new X509Certificate2Collection();

collection.Import(certPath, certPass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

//Then you can iterate over the collection:
foreach (X509Certificate2 cert in collection)
{
     // Bingo

     // Here you can do whatever you want with "cert"
}

- )

答案 1 :(得分:1)

我正在使用Eclipse的e(fx)clipse插件,它不会将您的CSS文件识别为有效的JavaFX CSS。我启动程序时没有得到异常,但它只是使用默认字体。

通过以下更改,正在加载和显示字体。

/**/
@font-face {
    font-family: Roboto; /* removed '' */
    src: url("Roboto-Thin.ttf");
}
#sampleLabel{
    -fx-font-family: Roboto ; /* added -fx- prefix */
}

答案 2 :(得分:1)

所以,差不多2年后,我遇到了自己对同样问题的反应。

但是在研究了com.sun.javafx.css.StyleManager的源代码之后,我现在有一个更酷,更优雅的解决方案:只需自己解析样式表并加载字体。

请在此处查看相关的源代码:lines 932-662

(是的,这一切都在Clojure中,但我相信你能搞清楚。)

我从这开始:

(defn add-stylesheet [^Scene scene path]
  (let [logger (Logging/getCSSLogger)
        level (.level logger)]
    (.setLevel logger PlatformLogger$Level/OFF)  ;; turn off logger
    (-> scene .getStylesheets (.add path))  ;; set stylesheet
    (.setLevel logger level) ;; turn logger back on
    (-> path stylesheet-parsed load-fonts))) ;; parse and load fonts

(由于某种原因,关闭日志记录不起作用。)

使用以下方法解析样式表:

(defn stylesheet-parsed [path]
  (.parse (CSSParser.) (cio/resource path)))

最后字体加载了这个:

(defn- load-fonts [^Stylesheet stylesheet]
  (doseq [^FontFace fontface (.getFontFaces stylesheet)]
    (doseq [^FontFace$FontFaceSrc ffsrc (.getSources fontface)]
      (let [src (-> ffsrc .getSrc (cs/replace "%20" " "))] ;; <- sanitizing path for Font/getFont
        (println "Loading font:" src)
        (let [f (Font/loadFont src 10.)]
          (println "Font loaded:" f))))))

这很好用,看起来很像原版。一个优点是,我们这里不检查类型URL,因此我们理论上可以将其扩展为更广泛地处理@ font-face。

这是load-fonts的更多Clojure-y实现,它返回所有加载字体的列表:

(defn- load-fontface-src [^FontFace$FontFaceSrc ffsrc]
  (-> ffsrc .getSrc (cs/replace "%20" " ") (Font/loadFont 10.)))

(defn- load-fontface [^FontFace ff]
  (map load-fontface-src (.getSources ff)))

(defn- load-fonts [^Stylesheet stylesheet]
  (vec (flatten (map load-fontface (.getFontFaces stylesheet)))))

需要进口:

(import
  '[com.sun.javafx.css.parser CSSParser]
  '[com.sun.javafx.css Stylesheet FontFace FontFace$FontFaceSrc]
  '[com.sun.javafx.util Logging]
  '[sun.util.logging PlatformLogger$Level])

TODO:
1.转变伐木。 (这很烦人,虽然只是开发中的一个问题。)
2.测试是否未加载任何字体,然后再进行替代解析和加载。但是,简单的检查可能需要与实际加载字体一样多的处理时间。

FIX: 在vec的左侧添加了flatten,以确保实现延迟的seq。

答案 3 :(得分:0)

对于像我一样仍然存在此问题,并且不希望或不知道如何使用Clojure的人,这里是仅使用Java的方法:
在将样式表添加到场景之前,请使用prometheus.yml ..... - job_name: celery-exporter static_configs: - targets: ['celery-exporter:8888']
,然后将在JavaFX中注册该字体,并且可以将Font.loadFont(getClass().getResourceAsStream([fontpath...]), [Some font-size, for example 12]); css-Property与已加载的字体一起使用。

答案 4 :(得分:0)

在我的情况下,这是由字体文件名中的'-'字符产生的,将其替换为'_'即可。

我确定字体系列必须是相同的文件名,但是要替换所有特殊字符''(空格)并分割驼峰大小写单词。

如此:

之前(无效):

@font-face {
    font-family: 'RifficFree Bold';
    src: url("../fonts/RifficFree-Bold.ttf");
}
.bingo-number, .label{
    -fx-font-family: 'RifficFree Bold';
}

(工作后):

@font-face {
    font-family: 'Riffic Free Bold';
    src: url("../fonts/RifficFree_Bold.ttf");
}
.bingo-number, .label{
    -fx-font-family: 'Riffic Free Bold';
}