Подтвердить что ты не робот

JavaFx Не удалось загрузить шрифт @font-face из-за com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged

Я уже задал аналогичный вопрос здесь, но кажется, что это было непонятно, так как у меня было много кода в проекте и я не мог опубликовать его здесь Поэтому пожалуйста не отмечайте как дубликат.

В связи с этим я решил создать новый проект с помощью 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]

Все файлы проекта находятся в одном пакете, а файл шрифта также присутствует в образце > production > TeamViewer > Roboto-Thin.ttf. Я также повысил с jdk-8u65 на jdk-8u66

Спасибо, любая помощь приветствуется.

4b9b3361

Ответ 1

Я нашел возможную причину и обход: Под капотом css-loader использует функцию Font.loadFont для загрузки шрифта в ваш CSS. Font.loadFont просто возвращает null, если он терпит неудачу, что дает "предупреждение".

Кажется, что эта функция не работает с %20 своей дорожкой/url-строкой. Поэтому вам нужно решить путь, а затем заменить его пробелом. Это означает, что вам придется загружать шрифты с кодом вместо 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

Я использую плагин e (fx) для Eclipse, который не распознает ваш файл CSS как действительный JavaFX CSS. Я не получаю исключения, когда я запускаю программу, но просто использует шрифт по умолчанию.

При следующих изменениях шрифт загружается и отображается.

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

Ответ 3

Итак, почти 2 года спустя, и я наткнулся на свой собственный ответ на ту же проблему, что и у меня.

Но теперь у меня есть более прохладное и более элегантное решение, изучив исходный код для com.sun.javafx.css.StyleManager: просто проанализируйте таблицы стилей и загрузите шрифты.

Смотрите исходный код здесь: строки 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.

Ниже приведена Clojure -y реализация load-fonts, которая возвращает список всех загруженных шрифтов:

(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, чтобы обеспечить выполнение ленивых секций.