由于com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged,JavaFx 无法加载@font-face 字体
JavaFx Could not load @font-face font because of com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
我已经问过一个类似的问题但似乎不清楚,因为我在项目中有很多代码并且不能post在这里所以请不要标记为重复。
因此,我决定创建一个新项目,其中只有一个 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]
All the project files are in one package and the font file is also present in the out>production>TeamViewer>sample>Roboto-Thin.ttf. I also upgraded from jdk-8u65 to jdk-8u66
谢谢,非常感谢任何帮助。
我正在使用 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 */
}
我找到了可能的原因和解决方法:
在引擎盖下 css-loader 使用函数 Font.loadFont
加载 CSS 中的字体。
Font.loadFont
简单地 returns null
如果失败,则给出 "warning".
似乎此功能不适用于 %20
它是 path/url-string。
所以你需要解析路径,然后用space替换它。
这意味着您必须使用代码而不是 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.))
;-)
所以,将近 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 实现,其中 returns 加载了所有字体的列表:
(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
,以确保实现lazy seqs。
对于那些像我一样仍然有此问题并且不想或不知道如何使用 Clojure 的人,以下是仅在 Java 中的使用方法:
在将样式表添加到您的场景之前,使用 Font.loadFont(getClass().getResourceAsStream([fontpath...]), [Some font-size, for example 12]);
字体将在 JavaFX 中注册,您可以使用 -fx-font-family
css -属性 使用加载的字体。
在我的例子中,这是由字体文件名中的“-”字符产生的,将其替换为“_”即可。
我确定字体系列必须是相同的文件名,但替换所有特殊字符 ' '(空白 space)并拆分驼峰式单词。
所以:
之前(没有工作):
@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';
}
我已经问过一个类似的问题
因此,我决定创建一个新项目,其中只有一个 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]
All the project files are in one package and the font file is also present in the out>production>TeamViewer>sample>Roboto-Thin.ttf. I also upgraded from jdk-8u65 to jdk-8u66
谢谢,非常感谢任何帮助。
我正在使用 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 */
}
我找到了可能的原因和解决方法:
在引擎盖下 css-loader 使用函数 Font.loadFont
加载 CSS 中的字体。
Font.loadFont
简单地 returns null
如果失败,则给出 "warning".
似乎此功能不适用于 %20
它是 path/url-string。
所以你需要解析路径,然后用space替换它。
这意味着您必须使用代码而不是 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.))
;-)
所以,将近 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 实现,其中 returns 加载了所有字体的列表:
(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
,以确保实现lazy seqs。
对于那些像我一样仍然有此问题并且不想或不知道如何使用 Clojure 的人,以下是仅在 Java 中的使用方法:
在将样式表添加到您的场景之前,使用 Font.loadFont(getClass().getResourceAsStream([fontpath...]), [Some font-size, for example 12]);
字体将在 JavaFX 中注册,您可以使用 -fx-font-family
css -属性 使用加载的字体。
在我的例子中,这是由字体文件名中的“-”字符产生的,将其替换为“_”即可。
我确定字体系列必须是相同的文件名,但替换所有特殊字符 ' '(空白 space)并拆分驼峰式单词。
所以:
之前(没有工作):
@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';
}