First we have to locate the jfxrt.jar, since it is not by default on the classpath. If you're using Windows or OS X or use the Oracle JVM on Linux it is simple to locate; It's inside the lib folder of the JRE directory.
For OpenJDK, you'll need the JavaFX Scene Builder 1.1 Developer Preview and install the delivered jfxrt.jar. You'll probably have to copy the whole lib folder distributed with the Scene Builder and partially replace the OpenJDK one.
Now use the following command to add JavaFX to your local Maven repository, and replace $JFXRTPATH with the path to the JRE lib folder:
mvn install:install-file \ -Dfile=$JFXRTPATH/jfxrt.jar \ -DgroupId=com.oracle \ -DartifactId=javafx-runtime \ -Dpackaging=jar \ -Dversion=2.2.0
You can now reference it in your Leiningen dependencies with
First I have to say the folks at Oracle really did a great job designing the API. It's much more straightforward to use and feels almost native in Clojure, especially when using the *Builder classes.
but there are a few things you'll want to do before using it:
- Don't use javafx.application.Application. That would mean to extend a class, and fortunately it is not necessary. Just add this line to your code:
(defonce force-toolkit-init (javafx.embed.swing.JFXPanel.))
- Create a shortcut to Platform.runLater. Really, this'll save you a lot of typework:
(defn run-later* [f] (javafx.application.Platform/runLater f)) (defmacro run-later [& body] `(run-later* (fn  ~@body))) (defn run-now* [f] (let [result (promise)] (run-later (deliver result (try (f) (catch Throwable e e)))) @result)) (defmacro run-now [& body] `(run-now* (fn  ~@body))) (defn event-handler* [f] (reify javafx.event.EventHandler (handle [this e] (f e)))) (defmacro event-handler [arg & body] `(event-handler* (fn ~arg ~@body)))
(Code snippets borrowed from the abandoned upshot library)
Example application See this gist for a small, REPL-compatible(!) hello-world-application (including project.clj).
How do I know when I have to use
run-later? For starting out, it's needed for Stage and Scene. Additionally you will get an "IllegalStateException Not on FX application thread" if you have some code that belongs inside a run-now or run-later.
Is there an actively developed library? Probably I'll work on one soon, in case I depend on JavaFX for my next project. I've started writing a little wrapper with convenience functions; You can find it here.