2012年12月5日水曜日

ClojureでJavaFX & Web Start

JavaFX Advent Calendar 2012
5日目の記事です。

三目並べ

Cojureで三目並べの続き。

ここでは三目並べのJavaFX実装について書きます。

ゲームのロジックは作ってあるのであとは描画のところを実装するだけ。

Application


JavaFXの基本として、メインクラスにjavafx.application.Applicationを継承します。

ここではgen-classを使って、Javaの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
mainメソッドではApplication.launchを呼び出します。

(defn -main [& args]
(Application/launch tic_tac_toe.main args))
view raw main.clj hosted with ❤ by GitHub
あとはstartメソッドでtic-tac-toe.game.Canvasを実装し、各パネルにhandlerを登録します。

(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
ClojureでGUIライブラリを使うときに便利なのがdoto。
あるインスタンスのもとで、メソッドを連続して実行することが出来ます。
Rubyのinstance_evalのようなものですね。

EventHandlerなどのインターフェースはreifyを使うことで実体を得られます。

Web Start


JavaFX Script時代にはいくつかWeb Startのアプリケーションを作ったことが
ありましたが、JavaFX 2になってからは初のWeb Startです。

まずは、lein2 uberjarでstandaloneなjarを作ります。
20MBもあるのはClojure+JavaFXのclassファイルが入ってる所為です。

次にjnlpですが、こんな感じになりました。

<?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
all-permissionsになっているのはClojureを実行するためです。
多分JRubyやGroovyでもall-permissionsが必要になるはず。

all-permissionsを要求するので、署名をしなければなりません。
keytoolで適当なkeystoreを作ります。

keytool -genkey -keystore foo -alias bar

fooというファイルが作られるので、jarsignerを使ってjarに署名します。

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

これでWeb Startで起動できます。
実際に試す場合はjnlpファイルのcodebaseを

codebase="file:/home/halcat0x15a/tic-tac-toe/"

のように書き替え、

javaws tic_tac_toe.jnlp

で実行可能です。

雑感


このプログラムではたいしたことをしていませんが、JavaFXのおかげで、Swingよりもシンプルで簡単にGUIを書けるようになったと思います。
他のGUIライブラリと比べても、ライブラリの設計は格段に良くなったと感じます。

Web Startは、ScalaやClojureなどのランタイムが他に必要な言語にはあまりむかないのかなと感じました。
プログラム+ライブラリ+ランタイムとなると、かなりファイルサイズが大きくなってしまいます。

0 件のコメント:

コメントを投稿