[英]JavaFX from Clojure repl
我开始学习Clojure,并且想尝试JavaFX for GUI。 我找到了这篇文章: http : //nailthatbug.net/2011/06/clojure-javafx-2-0-simple-app/ ,但是我想通过repl来启动它,以进行快速测试和方便。
因此,例如,我可以这样编写并查看新窗口:
(defn main-start []
(doto (JFrame. "Window!")
(.setSize (java.awt.Dimension. 400 300))
(.setVisible true)))
有什么办法用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 [])))
必须编译jfx.app命名空间才能启动应用程序,如果直接在REPL中运行代码,则该命名空间将无法工作。 如果要尝试使用代码,请按照说明在项目的README.md文件中使用Maven和Leiningen设置JavaFX。
尽管它仍处于起步阶段,但我已经能够使用Upshot从REPL中使用JavaFx。 主要技巧是完全忽略Application
并直接创建场景。 为此,您只需要强制运行时进行初始化即可,其示例可以在core.clj:69上看到。 另一个技巧是,几乎所有操作都必须包装在“立即run-now
块中,以确保其在JavaFX线程上运行。 与Swing相比,JavaFX对线程的选择更为挑剔。
非常感谢戴夫。 我还找到了javafx.embed.swing.JFXPanel的解决方案:
(ns to-dell3
(:import
(javafx.application Application Platform)
(java.util Date)
(javafx.scene Group Scene)
(javafx.scene.text Font Text)
(javax.swing JFrame SwingUtilities)
ChartApp1
javafx.scene.paint.Color
javafx.embed.swing.JFXPanel))
(defn launch-javafx [] (SwingUtilities/invokeLater
(proxy [Runnable] [] (run []
(let [frame2 (JFrame. "JFrame")
fxPanel2 (JFXPanel.)
]
(do
(.setSize frame2 500 200 )
(.setVisible frame2 true)
(.setDefaultCloseOperation frame2 JFrame/DISPOSE_ON_CLOSE)
(.add frame2 fxPanel2)
(Platform/runLater (proxy [Runnable] [] (run [] (let [root2 (Group.)
scene2 (Scene. root2 Color/ALICEBLUE)
text2 (Text.)]
(do
(.setX text2 40)
(.setY text2 100)
(.setFont text2 (Font. 25))
(.setText text2 "Welcome to Clojure + REPL + JavaFX!")
(.add (.getChildren root2) text2)
(.setScene fxPanel2 scene2)
)))))))))))
需要JavaFX 2.2。 而且在REPL中,这是这样的:(Platform / setImplicitExit false)这是此代码的直接端口: 将JavaFX集成到Swing应用程序中,因此它看起来非常必要和幼稚,因为在Clojure世界中,我可能是个经验丰富的人,请重写此代码以更多Clojureish的方式。 无论如何,它现在对我有用,我考虑了两个启动器的概念:一个通过(launch-javafx)用于基于repl的开发,一个用于发布:通过普通的javafx.application.Application启动器。 我仍然不知道它们是否彼此等效(我的意思是在javafx.embed.swing.JFXPanel情况下可以使用完整的JavaFX API),如果可以的话,这很适合我的目标(通过REPL开发)。 而且我仍在调查Upshot代码-也许会发现它更温和。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.