作为背景,我意识到Stack Overflow上还有大约5篇关于此问题的文章,我已经查看了这些回复,并且在没有真正解决方案的情况下研究了无数个小时 . 否则我不会在这里发布 .
我是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意味着字体实际上没有加载 . 我甚至尝试了假的路径名,并且它们也没有错误地返回nil,所以Font / 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) . 我正在使用Sublime Text,所以我使用SublimeREPL在终端中使用Maven识别JavaFX:
$ 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/lib/ext/jfxrt.jar -Durl=file:/Users/vaniificat/.m2/repository
大多数JavaFX引用代码都有效,但是现在整个javafx.scene.control包都不起作用,这意味着没有标签,没有按钮,没有TextFields等......:
> (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%工作 . 哼!
I opened an issue on JIRA: https://bugs.openjdk.java.net/browse/JDK-8093894. Once this gets addressed I can more fully explore @jewelsea 's other suggestions.
2 回答
这些主要是建议而不是明确的解决方案
On @font-face
如果可以,请使用Java 8 . 它支持@font-face css notation(早期版本的JavaFX,如2.2不支持) . 它还有一个改进的字体系统,可能会更健壮 . 因为字体可以通过Java 8中的css加载,所以您可能不需要解决相对于类位置问题的加载资源 .
On Font.loadFont
您应该能够在尝试使用时使用
Font.loadFont
方法 . JavaFX 2.x支持自定义字体的初始版本 . 在普通Java中使用JavaFX加载字体有一些步骤:How to embed .ttf fonts is JavaFx 2.2? . 我知道你已经看过了它并没有帮助 - 只是将它包含在这里作为参考,以便真正了解clojure而不是JavaFX的人可能有助于解决这个问题 .Check that your target font is compatible
仔细检查您正在使用的特定字体是否已加载并在常规的基于Java的JavaFX应用程序中使用(只是为了确保平台上的字体文件和JavaFX系统之间不存在任何不兼容的内容) .
You may need further help
我不知道加载相对资源如何在clojure中工作(或者你的代码可能存在其他问题) - 但也许clojure专家可以发布另一个允许它工作的答案 . 您可能想要编辑您的问题以包含sscce .
Update: 正如所指出的那样,原来的答案没有直接回答OP 's question. I'已经创建了一个关于原始技术的情况,以防任何人感兴趣 .
这是一个做你想要的短程序 .
在这个项目中,我将字体文件放在
resources
,demo
的子目录中 - 存储了Clojure源 - 因此函数get-font-from-resource
中的"prefix" .看起来您可能在使用
loadFont
时遇到的问题是从URL
转换为String
表单 . 外部表单是从驱动器上的根目录开始的绝对路径 .Tip :你可能知道这一点,但有一点不断让我困惑的是JavaFX中需要
double
参数的方法,比如Font/loadFont
. 我习惯于Java只是将整数参数提升为double . 在Clojure中,如果使用需要double的整数,程序将失败并显示一条不太有用的错误消息 .