このページでは、JavaFXで、Javaのクラスを使用するための第一歩について紹介する。
[追記]
このページを見てくださった方から連絡を頂き、
JavaFX ScriptからJavaのクラスを使用する方法について
違う方法のご紹介を頂きました。(追記090916)
ありがとうございます。
[さらに追記]ここ
考えてみれば、当たり前の気がしてきた、というメモ。
[さらに追記2]ここ
結局、Null Pointer Exceptionが出ないっていうことが原因だったのだ、というメモ
(詳しくHackしてないので)なぜかは、わからん。。。
NetBeans6.*+JavaFX1.0
テンプレートのソースをもとに、Javaで書いたクラスを使用したサンプルを作っていく。
初期のテンプレートの状態では、以下のようなソースができているはずです。
/* * Main.fx * * Created on 2009/08/16, 12:40:23 */ package myjavafxcollaboration; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.text.Text; import javafx.scene.text.Font; /** * @author tatsuya */ Stage { title: "Application title" width: 250 height: 80 scene: Scene { content: [ Text { font : Font { size : 16 } x: 10 y: 30 content: "Application content" } ] } }
この状態で、主プロジェクトを実行(F6)すると、
のようなウィンドウ※ができる。
※ちなみに、このようなスクリーンショットは、ウィンドウをアクティブにして[Alt]+[Print Screen]を押すことで取得できる。
Javaのプログラムを書く前に、.fx側で使いやすいように準備しておく。
/* * Main.fx * * Created on 2009/08/16, 12:40:23 */ package myjavafxcollaboration; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.text.Text; import javafx.scene.text.Font; /** * @author tatsuya */ var label:String = "Hello, World!"; Stage { title: "MyJavaFXCollaboration" width: 250 height: 80 scene: Scene { content: [ Text { font : Font { size : 24 } x: 10 y: 30 content: label; } ] } }
大事な部分は、Textのcontentアトリビュートに、直接、値を入れるのではなく、
labelという変数を介しているところである。
labelには、"Hello, World!"という値が入っているので、この状態で実行すると
のようになる。
現在のプロジェクトのパッケージにJavaのソースを追加する。
すると、以下のようなソースができる。
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package myjavafxcollaboration; /** * * @author tatsuya */ public class Foo { }
JavaFXから使うための公開関数get()を定義して次のように書き換えておく。
public class Foo { private String bar = "bar"; public String get() { return bar; } }
さて、.fxファイルの方に戻って先ほど作ったFooクラスを使ってみる。
get()関数は、String型の変数を返すので、そのままlabelに代入できる。
var label:String = "Hello, World!"; var foo:Foo; label=foo.get();
予想通りならば、"Hello, World!"が"bar"で上書きされて表示されるはずである。
実行結果
なにも表示されなかった。。。
なおかつ、コンパイルエラーもでないというややこしい現象である。
結論から言えば、
外から参照されるJavaクラスのなかの変数(実質的に公開関数も※)
にstatic修飾子をつけて宣言しておく。
※Javaでは、static変数は、static関数からしか参照できない。
public class Foo { private static String bar = "bar"; public static String get() { return bar; } }
まだ、詳しく調べたわけではないが、 メモリ管理うんちゃらの問題だと思う。
上記の方法では、既存のjavaでかいたクラスを書き換える(static修飾子)をつける必要があった。
しかし、JavaFXのソース側だけで対応できるとの情報を頂いたのでここに追記として掲載する。
var label:String = "Hello, World!"; //var foo:Foo; var foo = new Foo(); label=foo.get();
このように記述すればよい。
この方法の方が、メジャーなのかもしれない。
さて、JavaFX風の宣言(var foo:Foo;)とJava風の宣言(var foo = new Foo();)が、 実行に違いを生んでいたようだ。
バグなのか、哲学なのか。。。ちょっと気になるところだ。
var foo:Foo;
と
var foo = new Foo();
の違いであーだこーだ言ってたが、
JavaFXでは、
右辺から方が推測できるとき、以下のfoo2のように略記できる。
var foo1 = new Foo(); var foo2 = foo1;
また、foo1のほうも
var foo1:Foo = new Foo();
を略記してあるものとみなせる。
・・・つまり、
ちゃんとインスタンス化してその参照を管理してるかどうかなのかな。。。
javaで、
Foo foo;
とかしたら、NULLオブジェクトができるが、
どうやら、JavaFX Scriptの方では、
プリミティブ型も、javaとは違う初期値を与えらているらしいので、
もしかしたら、
staticでないほうの
var foo:Foo; foo.get();
は
javaでいうNullPointerException?みたいな状態なのかもしれない。
JavaFX ScriptがGUIの(プログラマにとっての)操作性を主眼においているとすれば、 処理的な部分は、Javaで書くのが自然な棲み分けだろう。
(Javaの)常識的に考えれば、
上記(本文中)、
var label:String = "Hello, World!"; var foo:Foo; label=foo.get();
は、
明らかに、Nullオブジェクト(?)に対するメソッド呼び出しだ。 (メソッドがstatic宣言されていない限りは!)
しかし、
JavaFX Script上で、このように記述された場合、
実行時にNullPointerException?が発生しない。
ちなみに、
インスタンスfooに関して、
foo == null
の値は、
true
となります。
参考まで。