Clojure JavaFX 实时操作
Clojure JavaFX Live Manipulation
我创建了一个简单的“Hello, World!”使用 JavaFX 的 Clojure 应用程序。
有很多类似的,但这一个是我的,就像步枪手的信条一样。此外,这个适用于最新的 JavaFX,并且不使用 Swing JFX 面板:
(ns ezclj.core
(:gen-class :extends javafx.application.Application)
(:import (javafx.application Application)
(javafx.fxml FXMLLoader)
(javafx.scene Scene Group)))
(def _app (atom nil))
(defn -start [app stage]
(reset! _app app)
(.setTitle stage "Hello From Clojure!")
(let [f (Scene. (FXMLLoader/load (.getResource (.getClass app) "sample.fxml")) 800 600)
_ (.setScene stage f)])
(.show stage)
(println "Running but doesn't return to REPL"))
(defn -main
[& args]
(Application/launch ezclj.core (into-array String [])))
如果我在 REPL 中启动它并使用 (-main) 启动它,则会出现 window。我的第一个问题是为什么这样做有效?正在启动 Leiningen 编译 ezclj.core class?如果没有,Application/launch 怎么能找到所说的 class?
现在,这会显示 sample.fxml 中的任何内容并继续其愉快的方式...这很好...但是挂断了 REPL...这很糟糕。但是,如果我创建一个线程:
(def t (Thread. (fn[] (-main))))
(.start t)
REPL 可用,我可以直接访问 _app,这引出了我的第二个问题:我现在可以通过 _app 更改 JFX 图来安全地构建我的 UI 吗?还是我忽略了一些东西,比如 JFX 线程上的潜在冲突?
我没有玩过 JavaFX,但从你的问题中可以清楚地看出 Application/launch
正在阻塞主线程。因此,正如您所发现的那样,在另一个线程中启动它就是答案。一个更简单的方法是使用:
(defn -main
[& args]
(future
(Application/launch ezclj.core (into-array String []))))
因为 future
获取表达式主体并在另一个线程中调用它们。
请查看 this list of documentation,尤其是 Clojure CheatSheet。
尽情享受吧!
P.S.
一旦掌握了基础知识,您可能会发现 lein-test-refresh
插件的“自动重新加载”工作流程很有用。
如果您遵循 this template project 中的模式,lein-test-refresh
插件将在每次保存文件后重新加载并重新编译您的代码。
您可以从单元测试中调用 -main
,这样它会在每次保存文件后 运行。
我创建了一个简单的“Hello, World!”使用 JavaFX 的 Clojure 应用程序。
有很多类似的,但这一个是我的,就像步枪手的信条一样。此外,这个适用于最新的 JavaFX,并且不使用 Swing JFX 面板:
(ns ezclj.core
(:gen-class :extends javafx.application.Application)
(:import (javafx.application Application)
(javafx.fxml FXMLLoader)
(javafx.scene Scene Group)))
(def _app (atom nil))
(defn -start [app stage]
(reset! _app app)
(.setTitle stage "Hello From Clojure!")
(let [f (Scene. (FXMLLoader/load (.getResource (.getClass app) "sample.fxml")) 800 600)
_ (.setScene stage f)])
(.show stage)
(println "Running but doesn't return to REPL"))
(defn -main
[& args]
(Application/launch ezclj.core (into-array String [])))
如果我在 REPL 中启动它并使用 (-main) 启动它,则会出现 window。我的第一个问题是为什么这样做有效?正在启动 Leiningen 编译 ezclj.core class?如果没有,Application/launch 怎么能找到所说的 class?
现在,这会显示 sample.fxml 中的任何内容并继续其愉快的方式...这很好...但是挂断了 REPL...这很糟糕。但是,如果我创建一个线程:
(def t (Thread. (fn[] (-main))))
(.start t)
REPL 可用,我可以直接访问 _app,这引出了我的第二个问题:我现在可以通过 _app 更改 JFX 图来安全地构建我的 UI 吗?还是我忽略了一些东西,比如 JFX 线程上的潜在冲突?
我没有玩过 JavaFX,但从你的问题中可以清楚地看出 Application/launch
正在阻塞主线程。因此,正如您所发现的那样,在另一个线程中启动它就是答案。一个更简单的方法是使用:
(defn -main
[& args]
(future
(Application/launch ezclj.core (into-array String []))))
因为 future
获取表达式主体并在另一个线程中调用它们。
请查看 this list of documentation,尤其是 Clojure CheatSheet。
尽情享受吧!
P.S.
一旦掌握了基础知识,您可能会发现 lein-test-refresh
插件的“自动重新加载”工作流程很有用。
如果您遵循 this template project 中的模式,lein-test-refresh
插件将在每次保存文件后重新加载并重新编译您的代码。
您可以从单元测试中调用 -main
,这样它会在每次保存文件后 运行。