2012年12月17日月曜日

JavaFX & Web Start with Clojure

This article is the 5th of JavaFX Advent Calendar and a sequel of Tic-tac-toe with Clojure.

Tic-tac-toe

Since the logic of the game have been made, we only need to implement at the drawing.

Application


As the basis for JavaFX, inherit javafx.application.Application to the main class.

In order to compile the class files of Java, we use the gen-class.

(ns tic-tac-toe.main
(:refer-clojure :exclude [==])
(:use [clojure.core.logic])
(:require [tic-tac-toe.game :as game])
(:gen-class
:extends javafx.application.Application)
(:import
[javafx.application Application]
[javafx.scene Scene Group]
[javafx.event EventHandler]
[javafx.scene.canvas Canvas]
[javafx.scene.shape Rectangle Circle Line]
[javafx.scene.text Text Font]
[javafx.scene.paint Color]))
view raw ns.clj hosted with ❤ by GitHub
In the main method calls Application.launch.

(defn -main [& args]
(Application/launch tic_tac_toe.main args))
view raw main.clj hosted with ❤ by GitHub
In the start method implements tic-tac-toe.game.Canvas and register the handler in each panel.

(defn -start [this stage]
(let [root (Group.)
scene (Scene. root)
children (.getChildren root)
canvas (reify game/Canvas
(draw-circle [this panel]
(.add children
(Circle. (+ (:x panel) game/radius)
(+ (:y panel) game/radius)
game/radius)))
(draw-cross [this panel]
(let [{:keys [x y]} panel
x' (+ x game/panel-size)
y' (+ y game/panel-size)]
(doto children
(.add (Line. x y
x' y'))
(.add (Line. x' y
x y')))))
(draw-text [this s]
(.add children
(doto (Text. 0 game/font-size s)
(.setFont font)
(.setFill Color/GRAY)))))]
(doseq [panel game/panels]
(.add children
(doto (Rectangle. (:x panel)
(:y panel)
game/panel-size
game/panel-size)
(.setFill Color/WHITE)
(.setStroke Color/BLACK)
(.setOnMouseClicked (reify EventHandler
(handle [this event]
(game/play canvas panel)))))))
(doto stage
(.setTitle "Tic Tac Toe")
(.setScene scene)
(.setMinHeight game/window-size)
(.setMinWidth game/window-size)
(.setResizable false)
(.show))))
view raw start.clj hosted with ❤ by GitHub
doto is useful when using the GUI library in Clojure.
We can run continuously some methods under the instance.
It is like the instance_eval in Ruby.

Such an interface as EventHandler is obtained an instance by using reify.

Web Start


First, make a standalone jar file with lein2 uberjar.

Then create a jnlp file.

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" xmlns:jfx="http://javafx.com" codebase="http://halcat0x15a.github.com/tic-tac-toe/" href="tic_tac_toe.jnlp">
<information>
<title>Tic Tac Toe</title>
<vendor>baskingcat</vendor>
<homepage href="http://halcat0x15a.github.com/tic-tac-toe/"/>
<description>tic tac toe</description>
<offline-allowed />
</information>
<security>
<all-permissions />
</security>
<resources>
<j2se version="1.7+" />
<jar href="target/tic-tac-toe-0.1.0-SNAPSHOT-standalone.jar" main="true" />
</resources>
<application-desc main-class="tic_tac_toe.main"></application-desc>
</jnlp>
view raw jnlp.xml hosted with ❤ by GitHub
The all-permissions are needed to run Clojure.

We must make a signature, because it requires all-permissions.

You can make the keystore by keytool, and sign the jar using jarsigner.

keytool -genkey -keystore foo -alias bar
jarsigner -keystore foo target/tic-tac-toe-0.1.0-SNAPSHOT-standalone.jar bar

You can start with Web Start.

If you try on local environment, rewrite the codebase of jnlp file.

Miscellaneous Thoughts


I think that JavaFX is simpler than Swing and we would be able to write the GUI application easily.

But I felt that the Web Start is not suitable for other required language runtime, such as the Scala and Clojure.
Because file size becomes very large.

0 件のコメント:

コメントを投稿