tutorial example java javafx java-8 javafx-2 javafx-8

example - JavaFx no se pudo cargar la fuente @ font-face debido a com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged



javafx scene builder (3)

Estoy usando el plugin e (fx) clipse para Eclipse, que no reconoce su archivo CSS como JavaFX CSS válido. Sin embargo, no obtengo la excepción cuando inicio el programa, simplemente usa la fuente predeterminada.

Con los siguientes cambios, la fuente se carga y muestra.

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

Ya había hecho una pregunta similar aquí, pero parece que no estaba claro ya que tenía un montón de código en el proyecto y no pude publicarlo aquí. Por favor , no marquen como duplicado.

Por eso, decidí crear un nuevo proyecto con solo una etiqueta para hacer que el código sea pequeño y limpio, y también para eliminar a otros potenciales sospechosos del error que estoy recibiendo.

Así que aquí está mi código fuente de 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); } }

Y este es mi archivo css

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

Este es el error que estoy obteniendo en 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]

Todos los archivos del proyecto están en un paquete y el archivo de fuente también está presente en la salida> producción> TeamViewer> muestra> Roboto-Thin.ttf. También actualicé de jdk-8u65 a jdk-8u66

Gracias, cualquier ayuda es muy apreciada.


Encontré la posible causa y una Font.loadFont : bajo el capó, el cargador css usa la función Font.loadFont para cargar la fuente en tu CSS. Font.loadFont simplemente devuelve null si falla, lo que da la "advertencia".

Parece que esta función no funciona con %20 it su ruta / url-string. Por lo tanto, debe resolver la ruta y luego reemplazarla con un espacio. Eso significa que tendrá que cargar sus fuentes con código en lugar de con CSS (por ahora).

En Clojure, mi trabajo se parece a esto:

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

;-)


Entonces, casi 2 años después, y encontré mi propia respuesta al mismo problema que todavía tengo.

Pero ahora tengo una solución más fresca y más elegante, después de estudiar el código fuente de com.sun.javafx.css.StyleManager : simplemente analizo las hojas de estilo y las fuentes.

Ver el código fuente relevante aquí: líneas 932-662

(Sí, todo esto está en Clojure, pero estoy seguro de que puedes resolverlo).

Comienzo con esto:

(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

(Desactivar el registro no funciona, por alguna razón).

La hoja de estilo se analiza con esto:

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

Y finalmente las fuentes se cargan con esto:

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

Esto funciona bien y se parece mucho al original. Una ventaja es que aquí no buscamos únicamente el tipo de URL, por lo que podríamos extenderlo en teoría para manejar @ font-face de forma más exhaustiva.

Aquí hay una implementación más de Clojure-y de load-fonts que devuelve una lista de todas las fuentes cargadas:

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

Y las importaciones necesarias:

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

QUE HACER:
1. Giro del registro. (Es molesto, aunque solo es un problema en el desarrollo).
2. Pruebe para ver si no se cargaron las fuentes, y solo entonces para el análisis y la carga alternativos. Pero probablemente la simple verificación requeriría tanto procesamiento como en realidad cargar las fuentes un tiempo extra.

REVISIÓN: se agregó vec a la izquierda de flatten , para garantizar que los seqs perezosos se realicen.