図形の描画
では、GUIはこの辺にして、今度はグラフィック関係について見てみることにしましょう。グラフィックの描画も、やはり宣言を使って記述することができます。ただし、これにはFrameではなく「Canvas」を使います。Canvas! 実に懐かしいクラス名です。といっても、AWTのCanvasではなく、あくまでJavaFXのCanvasなんですが……。
import javafx.ui.*; import javafx.ui.canvas.*; var window = Frame { title:"JavaFX!" width:400 height:300 content:Canvas { content:[ Rect { x:50 y:50 width:100 height:100 stroke:black strokeWidth:3 fill:red }, Ellipse { cx:200 cy:200 radiusX:100 radiusY:50 stroke:black strokeWidth:3 fill:yellow }, Star { cx:175 cy:125 rin:30 rout:70 points:5 startAngle:30 stroke:black fill:green strokeWidth:3 }, Text { x:25 y:225 content:"This is JavaFX!" font: new Font("Impact", "BOLD", 36) stroke:blue fill:cyan strokeWidth:2 } ] } }; window.visible = true;

例としてごく単純な図形をいくつか描画するサンプルを挙げておきました。四角形、楕円、星型、テキストといったものを描画しています。ソースコードを見ると、Canavsのcontentにいくつもの図形の宣言が記述されていることが分かりますね。これは、実は配列の値をcontentに設定しているのです。よくみると、content:[○,○,○]といった形で書かれていることが分かるはずです。
ここで使った図形の宣言は、Rect、Ellipse、Start、Textといったものです。この他にも、正円であるCircle、直線のLine、多角形のPolygon/Polyline、曲線のCubicCurve/QuadCurveなど多数の図形宣言が用意されています。これらの宣言を記述していくのが、Canvasにおける描画の基本スタイルです。
これらの図形には多くの属性が用意されています。位置や大きさを示すものの他、線分の色を示すstroke、内部の塗りつぶし色を示すfill、線分の幅を示すstrokeWidthといったものが標準で用意されています。注目すべきは、これらが図形だけでなくテキストにも用意されている点です。テキストの輪郭部分と内部を別々に塗りつぶすというようなことが簡単に行えるのです。
では、イメージを読み込んで描画する場合はどうすればよいのでしょうか。この場合には、「ImageView」という部品をCanvasに配置し、そこにイメージを設定することで表示させることができます。例として、同じ階層にある「sample.jpg」というイメージを表示させるサンプルを挙げておきましょう。
import javafx.ui.*; import javafx.ui.canvas.*; var window = Frame { title:"JavaFX!" width:400 height:300 content:Canvas { content:ImageView { transform:translate(25,25) image:Image { url:"./sample.jpg" } } } }; window.visible = true;

CanvasのcontentにImageViewが用意され、その中のimage属性にImageという宣言が設定されているのが分かります。ここでurlに表示するイメージファイルのURLを指定することで、ImageViewにイメージを表示させています。
また、表示位置を調整するのに、transformという属性を設定してます。これは座標軸の変換により位置を調整するもので、Imageに限らずすべての図形で利用することができます。ImageViewにはxやyといった位置に関する属性がないので、transformを使って位置を調整していたわけです。
図形へのイベントの組み込み
このグラフィックは、JavaのGraphicsにある描画メソッドなどによる描画とはかなり性質が異なります。一番の特徴は、「図形にもイベントがある」という点でしょう。イベントの属性に実行する処理を割り当てることで、ボタンのように図形を利用することができるようになります。
import javafx.ui.*; import javafx.ui.canvas.*; class TextData { attribute message:String; } var textData = new TextData(); var window = Frame { title:"JavaFX!" width:400 height:300 content:Canvas { content:[ Text { x:25 y:25 font: new Font("Geneva", "PLAIN", 36) stroke:black fill:blue strokeWidth:1 content:bind textData.message }, Ellipse { cx:150 cy:150 radiusX:100 radiusY:50 stroke:black strokeWidth:3 fill:yellow onMousePressed:operation(e:CanvasMouseEvent){ textData.message = "pressed {e.x},{e.y}"; } onMouseReleased:operation(e:CanvasMouseEvent){ textData.message = "released {e.x},{e.y}"; } onMouseClicked:operation(e:CanvasMouseEvent){ textData.message = "clicked {e.x},{e.y}"; } } ] } }; window.visible = true;

これは、画面に表示してある楕円形にマウス関連のイベントを設定し、マウスボタンを押し下げたり離したりするとその位置の情報を表示させるようにした例です。ここでは、EllipseのonMousePressed、onMouseReleased、onMouseClickedといった属性に、実行する処理をoperationで定義し組み込んでいます。これらのイベント用の属性に組み込むoperationではCanvasMouseEventという引数が用意され、これを利用してイベントに関する情報を取得できます。
また、ここではTextでテキストを表示していますが、モデルへのバインドを行うことで、イベントが発生すると表示されているテキストを変更するようにしていることが分かるでしょう。グラフィックでも、バインドは利用できます。これにより、リアルタイムに変化するグラフィックを作成することが簡単にできるようになります。
まとめ
以上、JavaFXを使ったアプリケーション開発がどのようになるのか、その基礎部分をかいつまんで説明してきました。JavaFXによるプログラミングがどんなものか、そのイメージぐらいはつかめたでしょうか。
JavaFXは、基本的な文法はJavaに近いのですが、実際にコーディングをすると、Javaとはかなり違った言語であることが実感できるはずです。何より、宣言によるGUIの記述は、プログラミング言語というより、HTMLのようなページ記述言語を書いているかのような錯覚に陥ることでしょう。
JavaFXの中に、長々とした複雑な処理を書こうとすると、ややもすれば隔靴掻痒な思いをするかもしれません。operationやfunctionといった機能により複雑な処理も記述することはできるのですが、それらもJavaFXの一つの要素でしかありません。Java的な書き方が頭から離れないと、なかなか思うように書けず、いらいらするかも知れません。
ただし、モデルの設計とバインドによる値の関連付けは、仕組みが飲み込めると実に気持ちよく各種の値の変更処理を簡略化できます。JavaFXを使ってから改めてJavaのクラス定義を見ると、全体の構造がソースコードからなかなか見えてこない作りになっていることがよく分かります。
少なくともGUIに関する限り、JavaFXによる構造化は実に小気味よくGUIを整理してくれます。今後のJavaのあり方にも大きな影響を与えるだろうJavaFX。ぜひ、今のうちから試しておきたいものです。
