2013-08-06 55 views
2

作爲背景,我意識到在Stack Overflow上大約有5篇關於此的文章,bur我查看了這些響應,並且在無數個小時內研究了這些並沒有真正的解決方案。否則我不會在這裏發佈。在JavaFX + Clojure中加載自定義字體

我是JavaFX的新手,我喜歡Clojure,所以我使用Github上的chrisx的clj-javafx項目作爲JavaFX的Clojure包裝器。大多數操作都很好,例如將組件放置在場景/舞臺上並使用CSS對其進行樣式設置。只有一個問題:我想導入自定義字體,到目前爲止我還沒有辦法。

我試過多種方法。的第一件事Java版本我試過是:

Font.loadFont(<myClass>.class.getResource("mpsesb.ttf").toExternalForm(), 14); 

我試圖使用Java的互操作做,在Clojure的,但我不知道的Clojure如何處理Java類。相反,我用clojure.java.io.resource:

(use '[clojure.java.io :only [resource]]) 
(resource "mpsesb.tff") 

而且它打印.ttf文件的URL就好了。 然後我嘗試使用該URL並將其用作Font.loadFont方法中的參數,該方法無效。玩弄認真100排列點運算符和Java方法和類後,我得到了下面不打印任何錯誤,不像其他組合我想:

(Font/loadFont "fonts/ttf/mpsesb.ttf") 

,但它只是返回nil,其中根據JavaFX API意味着字體沒有實際加載。我甚至嘗試假路徑名,他們也沒有錯誤返回零,所以字體/ loadFont函數似乎不如我想象的那麼有前途。

我最後用CSS來加載,而不是使用Java將其導入字體嘗試:

@font-face { 
    font-family: 'MyrProSemiExtBold'; 
    src: url('file:/Users/<restOfPath>/mpsesb.ttf'); 
} 
.label { 
    -fx-font-size: 14px; 
    -fx-font-weight: normal; 
    -fx-font-family: 'MyrProSemiExtBold'; 
} 

,但沒有運氣。這些標籤在14點處顯示爲默認字體(Lucida Grande)。

非常感謝您提供任何建議。

編輯:

謝謝,@ jewelsea。讀完你寫的東西后,我做的第一件事就是獲得Java 8 + JDK 8(build b101)。我使用的是崇高的文本,所以我就SublimeREPL JavaFX的使用Maven像這樣在終端識別:

$ mvn deploy:deploy-file -DgroupId=local.oracle -DartifactId=javafxrt -Dversion=8.0 -Dpackaging=jar -Dfile=/System/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/l‌​ib/ext/jfxrt.jar -Durl=file:/Users/vaniificat/.m2/repository 

大多數JavaFX的指涉代碼的工作,但現在整個javafx.scene.control軟件包不工作,這意味着沒有標籤,沒有按鈕,沒有的TextField,等...:

> (import javafx.scene.control.Button) 
: NoClassDefFoundError Could not initialize class javafx.scene.control.Button 
    java.lang.Class.forName0 (Class.java:-2) 
> (import javafx.scene.control.Label) 
: NoClassDefFoundError javafx.scene.control.Labeled 
    java.lang.Class.forName0 (Class.java:-2) 
> (import javafx.scene.control.TextField) 
: NoClassDefFoundError javafx.scene.control.Control 
    java.lang.Class.forName0 (Class.java:-2) 
> (import '(javafx.scene.control Button Label PasswordField TextField)) 
: NoClassDefFoundError Could not initialize class javafx.scene.control.Button 
    java.lang.Class.forName0 (Class.java:-2) 

一個可能的參考這些錯誤可能在https://forums.oracle.com/thread/2526150找到。基本上主要的是JavaFX 8只在測試階段,所以我們不能期望它能夠100%工作。哼!

我在JIRA上打開了一個問題:https://bugs.openjdk.java.net/browse/JDK-8093894。一旦得到解決,我可以更充分地探索@jewelsea的其他建議。

+0

對於Java 8,JavaFX類位於標準默認類路徑中,因此它們不應導入到Maven存儲庫中。我不知道SublimeREPL是如何工作的,但我認爲只要它使用Java 8 JRE啓動,它就能夠自動查找JavaFX類。您鏈接的論壇帖子與您未遇到的課程無關。 Java8是早期訪問,但基本上都是功能性的 - 像創建按鈕這樣的基本功能沒有問題。您可能希望創建一個單獨的StackOverflow問題,讓JavaFX 8能夠與Clojure一起使用。 – jewelsea

回答

2

這些大多是建議而不是最終的解決方案

在@字體面

使用Java 8如果你能。它支持@font-face css notation(JavaFX的早期版本,如2.2版本)。它也有一個更新的字體系統,可能會更強大一點。由於字體可以通過Java 8中的css加載,所以您可能不需要解決相對於類位置問題的加載資源。

在Font.loadFont

你應該能夠與您試圖用它來使用Font.loadFont方法。 JavaFX 2.x支持它的初始版本中的自定義字體。在JavaFX中以普通Java加載字體有一些步驟:How to embed .ttf fonts is JavaFx 2.2?。我知道你已經看過,並沒有幫助 - 只是將它包括在這裏供參考,這樣一個真正瞭解clojure而不是JavaFX的人可能會幫助解決問題。

檢查你的目標字體是兼容

仔細檢查您所使用的負載,並在常規的基於Java的JavaFX應用程序使用的特定字體(只是爲了確保沒有東西之間不兼容字體文件和您平臺上的JavaFX系統)。

您可能需要進一步的幫助

我不知道怎麼用Clojure加載相對資源工作是(或者也許有一些其他問題與您的代碼) - 但也許Clojure的專家可以發佈另一個答案允許它工作。您可能想編輯您的問題以包含sscce

2

更新:正如指出的那樣,原來的答案並沒有直接回答OP的問題。如果有人感興趣,我已經創建了有關原始技術的blog post

這是一個簡短的程序,可以做你想做的事。

(ns demo.core 
    (:gen-class 
    :extends javafx.application.Application) 
    (:import 
    [javafx.application Application] 
    [javafx.event EventHandler] 
    [javafx.scene Scene] 
    [javafx.scene.control Button] 
    [javafx.scene.layout StackPane] 
    [javafx.scene.text Font]) 
    (:require [clojure.java.io :as jio])) 

(defn- get-font-from-resource 
    "Load the named font from a resource." 
    [font-name] 
    (let [prefix "demo/resources/" 
     url (jio/resource (str prefix font-name)) 
     fnt (Font/loadFont (.toExternalForm url) 20.0)] 
    fnt)) 

(defn -start 
    "Build the application interface and start it up." 
    [this stage] 
    (let [root (StackPane.) 
     scene (Scene. root 600 400) 
     fnt (get-font-from-resource "ITCBLKAD.TTF") 
     btn (Button. "Press Me!")] 

    (.setOnAction btn 
        (reify EventHandler 
        (handle [this event] 
         (doto btn 
         (.setText (str "This is " (.getName fnt))) 
         (.setFont fnt))))) 

    (.add (.getChildren root) btn) 

    (doto stage 
     (.setTitle "Font Loading Demo") 
     (.setScene scene) 
     (.show)))) 

(defn -main 
    [& args] 
    (Application/launch demo.core args)) 

在該項目中,我放置在字體文件中resources,的demo子目錄 - 其中所述的Clojure源被存儲 - 因此在功能get-font-from-resource「前綴」。

看起來您可能遇到的問題loadFont在您從URL轉換爲String表單時出現。外部窗體是從驅動器根目錄開始的絕對路徑。

提示:你可能知道這一點,但有一兩件事,不斷螺絲我在JavaFX的需要double參數,如Font/loadFont方法。我習慣於Java,只是推動整數參數加倍。在Clojure中,如果使用需要double的整數,程序將失敗並顯示不太有用的錯誤消息。

+1

我想亞歷克斯試圖加載沒有安裝在Windows上的字體,而是與他的應用程序一起發貨([使用自定義字體](http://docs.oracle.com/javafx/2/text/jfxpub-text)。 htm)部分的JavaFX文本教程)。 – jewelsea

+0

@jewelsea:是的,原來的答案並不適用。我刪除了它,並寫了更適用的內容。 – clartaq