gpt4 book ai didi

Clojure 无法使用静态初始值设定项导入 JavaFX 类

转载 作者:行者123 更新时间:2023-12-04 15:34:11 25 4
gpt4 key购买 nike

我在玩 Clojure (1.6) 和 JavaFX 8,一开始我就遇到了问题。例如,这个非常简单的代码失败了:

(ns xxyyzz.core)

(gen-class :name "xxyyzz.core.App"
:extends javafx.application.Application
:prefix "app-")

(defn app-start [app stage]
(let [button (javafx.scene.control.Button.)]))

(defn launch []
(javafx.application.Application/launch xxyyzz.core.App (into-array String [])))

(defn -main []
(launch))

这是堆栈跟踪的最后一部分似乎相关:

Caused by: java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at clojure.lang.RT.classForName(RT.java:2070)
at clojure.lang.Compiler$HostExpr.maybeClass(Compiler.java:969)
at clojure.lang.Compiler$HostExpr.access$400(Compiler.java:747)
at clojure.lang.Compiler$NewExpr$Parser.parse(Compiler.java:2494)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
... 48 more
Caused by: java.lang.IllegalStateException: Toolkit not initialized
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:276)
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:271)
at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:562)
at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:524)
at javafx.scene.control.Control.<clinit>(Control.java:81)
... 55 more

我根本不会说 Java,但研究这个问题似乎出在 Clojure 及其导入 Java 类的方式上。如果我理解正确,在导入时它会运行类静态初始值设定项,并且对于某些 JavaFX 类(在我的情况下为 Button)会崩溃。

猜猜我有两个问题:我对这个错误的理解正确吗?其次,有没有办法以某种方式解决这个问题?我试过在 (ns) 声明中拉入函数内部的导入,但它仍然不起作用。

如果没有 Clojure 修复,是否可以通过一些额外的 Java 代码来修复?

欢迎任何提示和指示!

最佳答案

我找不到改变 Clojure 导入行为的方法,但我确实找到了一些技巧来做我需要的。

首先,JavaFX 提供了构建器类,因此在这种特殊情况下最简洁的方法是使用 ButtonBuilder创建新按钮。

第二种方法是编写一个简单的 Java 类来包装 Button ,然后从 Clojure 的侧面导入该包装类。当处理数量较少的问题类时,这是一个不错的解决方案。

第三种方法是在运行时导入,就像这样(感谢#clojure 的人帮助解决这个问题):

(defn import-at-runtime [name]
(.importClass (the-ns *ns*)
(clojure.lang.RT/classForName name)))

(import-at-runtime "javafx.scene.control.Button")

(let [button (eval `(new ~(symbol "javafx.scene.control.Button") ~"Button Text"))

最后,这在 Clojure 的 Java 互操作中似乎是一个丑陋的疣,如果将来可以修复它会很棒。

更新:还有 clojure.lang.RT/classForNameNonLoading ,但不幸的是,它不是 public从 Clojure 1.6 开始。不过,在 Clojure 中重新实现它很容易:
(fn [^String class-name]
(Class/forName class-name false (clojure.lang.RT/baseLoader)))

稍后,可以使用 clojure.lang.Reflector/invokeConstructor 实例化该类。 .

关于Clojure 无法使用静态初始值设定项导入 JavaFX 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23365409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com