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

huus2vyu  于 2023-05-21  发布在  Java
关注(0)|答案(6)|浏览(322)

我已经问了一个类似的问题here,但似乎它不清楚,因为我有很多的代码在项目中,不能张贴在这里,所以不要标记为重复。
因此,我决定创建一个新项目,其中只有一个Label,以使代码小而干净,并消除其他潜在的错误嫌疑人
这是我的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>sample> Roboto-Thin. ttf中。我也从JDK-8 U65升级到了JDK-8 U66
谢谢,任何帮助都非常感谢。

jfgube3f

jfgube3f1#

我找到了可能的原因和解决方法:css-loader使用函数Font.loadFont在CSS中加载font-face。如果失败,Font.loadFont简单地返回null,给予“警告”。
这个函数似乎不适用于%20路径/url-string。因此,您需要解析路径,然后将其替换为空格。这意味着你将不得不用代码而不是CSS来加载你的字体(现在)。
在Clojure中,我的解决方法看起来像这样:

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

;-)

odopli94

odopli942#

我使用的是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 */
}
enyaitl3

enyaitl33#

所以,差不多两年后,我遇到了我自己的React,同样的问题,我仍然有。
但是现在我有了一个更酷、更优雅的解决方案,在研究了com.sun.javafx.css.StyleManager的源代码之后:只需自己解析样式表并加载字体。
相关源代码请看这里:第932-662行
(Yes,这都是在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])

待办事项:
1.转向伐木。(这很烦人,尽管只是开发中的一个问题。)
2.测试是否有字体未加载,然后才进行替代解析和加载。但是,可能简单的检查将需要与实际加载字体一样多的处理时间。
修复:在flatten的左侧添加了vec,以确保实现惰性序列。

1sbrub3j

1sbrub3j4#

在我的例子中,这是由字体文件名中的“-”字符产生的,用“_”替换它,它就可以工作了。
我确定字体系列必须是相同的文件名,但替换所有特殊字符' '(一个空格)并拆分驼峰大小写单词。
所以:
之前(不工作):

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

工作(Working):

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

new9mtju5#

对于那些像我一样仍然有这个问题并且不想或不知道如何使用Clojure的人,这里是如何在Java中做到这一点:
在向场景中添加样式表之前,请使用Font.loadFont(getClass().getResourceAsStream([fontpath...]), [Some font-size, for example 12]);
然后字体将在JavaFX中注册,您可以将-fx-font-family css-Property用于加载的字体。

11dmarpk

11dmarpk6#

我在Reddit上找到了一个适合我的解决方案。这里是链接:Reddit post
在CSS样式表中定义字体系列时,请确保使用字体文件第一行中提到的确切名称。
例如,如果第一行显示“Pixeloid Sans”,则字体系列应指定如下:
-fx-font-family: "Pixeloid Sans";
我还删除了@font-face声明,因为它是不必要的。
最后,我应该提到我所有的.tff文件都位于/resources中的一个文件夹中。

相关问题