我开始学习Clojure,我想尝试使用JavaFX for GUI.我发现这篇文章:http://nailthatbug.net/2011/06/clojure-javafx-2-0-simple-app/ ,但我想通过repl启动它以便快速测试和方便.
所以,例如,我可以在repl中写这个并看到新窗口:
(defn main-start []
(doto (JFrame. "Window!")
(.setSize (java.awt.Dimension. 400 300))
(.setVisible true)))
Run Code Online (Sandbox Code Playgroud)
有没有办法用javafx.application.Application做这样的事情 - 看看新的JavaFX窗口?
谢谢.安德鲁.
如果您阅读JavaFX Application类文档,您将看到Application类是一个抽象类,无法直接实例化.这意味着,您至少必须创建javafx.application.Application的子类.
生命周期
JavaFX应用程序的入口点是Application类.无论何时启动应用程序,JavaFX运行时都会按顺序执行以下操作:
- 构造指定Application类的实例
- 调用init()方法
- 调用start(javafx.stage.Stage)方法
- 等待应用程序完成,当发生以下任何一种情况时会发生:应用程序调用Platform.exit()最后一个窗口已关闭且Platform上的implicitExit属性为true调用stop()方法请注意,start方法是抽象,必须被覆盖.
因此,你需要生成一个类 - 使用gen-class宏,因为它可以在博客文章中看到 - 使用start方法来启动应用程序.
编辑:使用添加的gen-class方法链接到示例应用程序
我在Clojure中创建了一个带有简单示例JavaFX应用程序的Github存储库.这是遵循gen-class方法的Clojure文件:
(ns jfx.app
(:import (javafx.beans.value ChangeListener ObservableValue)
(javafx.concurrent Worker$State)
(javafx.event ActionEvent EventHandler)
(javafx.scene Scene)
(javafx.scene.control Button)
(javafx.scene.layout StackPane)
(javafx.stage Stage)
(javafx.scene.web WebView)))
(gen-class
:name clj.jfx.App
:extends javafx.application.Application
:prefix "app-")
(defn app-start [app ^Stage stage]
(let [root (StackPane.)
btn (Button.)
web-view (WebView.)
state-prop (.stateProperty (.getLoadWorker (.getEngine web-view)))
url "http://clojure.org"]
;; Add a WebView (headless browser)
(.add (.getChildren root) web-view)
;; Register listener for WebView state changes
(.addListener state-prop
(proxy [ChangeListener] []
(changed [^ObservableValue ov
^Worker$State old-state
^Worker$State new-state]
(println (str "Current state:" (.name new-state)))
(if (= new-state Worker$State/SUCCEEDED)
(println (str "URL '" url "' load completed!"))))))
;; Load a URL
(.load (.getEngine web-view) url)
;; add a Button with a click handler class floating on top of the WebView
(.setTitle stage "JavaFX app with Clojure")
(.setText btn "Just a button")
(.setOnAction btn
(proxy [EventHandler] []
(handle [^ActionEvent event]
(println "The button was clicked"))))
(.add (.getChildren root) btn)
;; Set scene and show stage
(.setScene stage (Scene. root 800 600))
(.show stage)))
(defn app-stop
"Stop method is called when the application exits."
[app]
(println "Exiting application!")
)
(defn launch
"Launch a JavaFX Application using class clj.jfx.App"
[]
(javafx.application.Application/launch clj.jfx.App (into-array String [])))
Run Code Online (Sandbox Code Playgroud)
该jfx.app命名空间已被编译到启动应用程序,如果你在REPL直接运行的程序将无法正常工作.如果您想尝试代码,请按照项目的README.md文件中的Maven和Leiningen设置JavaFX的说明进行操作.
虽然它仍然处于起步阶段,但我已经能够使用Upshot从REPL中使用JavaFx .主要技巧是直接完全忽略Application和创建场景.要执行此操作,您只需要强制运行时进行初始化,其示例可以在core.clj:69中看到.另一个技巧是,你所做的几乎每件事都必须包装在一个run-now块中,以确保它在JavaFX线程上运行.JavaFX比Swing更挑剔线程.