今更だけどJavaFXを触ってみる

JavaFXって何?

  • JavaVM上で動くRIAプラットフォーム
  • コンパイルできるスクリプト言語
  • インタプリタ版もある
  • XMLみたいな記法でGUIを作っていけるので従来のSwingよりも書きやすい(はず)
  • もちろん今まで作ったJava生成物を利用することも可能
  • Java生成物 => JVM上で動くならJavaでもJythonでもJRubyでもおk!
  • GUIJavaFXで、内部ロジックは好きな言語で書ける
  • すなわちJavaFXは「Java + α」 Javaを超越した存在
  • でもあまり盛り上がってないのよね
  • AdobeAIRとSilverlightに負けてる感はある
  • 日本語で解説してるページはまだ少ない
  • 解説本もちょっと少ない(というかJavaFX1.2に対応した本ってあるのか?)
  • 細けぇことはいいん(ry

今更触ってみる理由

  • JavaFX1.0の時点ではLinux用のSDKが用意されて無かったのでちょっと触れなかった
  • JavaFX1.1からJavaFX1.2にかけて大幅な変更(後方互換性無し!)があったので、学ぶならJavaFX1.2!!

JavaFX1.2をインストールすると、大抵のページのJavaFXのJavaWebStartサンプルはJavaFX1.1用に書かれているので
動作しなくて多少がっかりしますが、そこはなんとか乗り越えていきましょう

SDKの入手

自分はNetBeansのプラグインから追加してやってみた
ツール > プラグインから「使用可能なプラグイン」 タブからJavaFX ComposerとJavaFX Kitを選択してインストール→再起動する

とりあえずHelloWorld(コマンドライン版)

最初はコマンドラインで試す!
自分はUbuntu9.10でNetBeans6.8rc1版を使ってますが、
~/.netbeans/6.8rc1/javafx-sdk/bin/以下にjavafxcコマンドとjavafxコマンドがあるので、
javacコマンドのように使うことでコンパイル→実行できます

ファイル名: HelloJavaFX.fx
println("Hello,World!!!!!!")

一行だけならセミコロンもいらない!
(厳密には最終行だけはセミコロン無しを許容してくれている仕様)

コンパイル&実行
# Pathを通す(ここは人それぞれ違う。OSにもよるので注意)
% PATH=$PATH:~/.netbeans/6.8rc1/javafx-sdk/bin/
% export PATH
# コンパイル
% javafxc HelloJavaFx.fx
# 実行
% javafx HelloJavaFx
# Hello, World!!!!!! と出力される

GUIを本格的に扱う前に色々と慣れておく

JavaJavaFXの構文の違い
変数宣言

Javaの場合

int i;
int j = 0;
double a = 3.14;

JavaFXの場合

var i;  //明示的な型指定無しでもOK
var i : Integer;   //型指定もできる
var j = 0;
var j : Integer = 0;
var a = 3.14;
var a : Double = 3.14

この辺はActionScriptに似てる

定数宣言

Javaの場合

final double M_PI = 3.14;

JavaFXの場合

def M_PI = 3.14;

finalではなくdefを使う

文字列

Javaの場合

String str = "黒い石だ!!\n伝承の通りだ!!"

JavaFXの場合

var str = "黒い石だ!!\n伝承の通りだ!!";  //ダブルクォート
var str : String = "黒い石だ!!\n伝承の通りだ!!";
var str = '黒い石だ!!\n伝承の通りだ!!'  //シングルクォート
var str : String = '黒い石だ!!\n伝承の通りだ!!'

シングルクォートでも文字列であると認識してくれることが違う

文字列の加算

Javaの場合

int a = 3;
String str1 = a + "分間待ってやる!!";
String str2 = "時間だ!!";
String str3 = "話を聞こう!!";
String str4 = str2 + str3;
System.out.println(str1 + str4); // 3分間待ってやる!!時間だ!!話を聞こう!!

JavaFXの場合

var a = 3;
var str1 = "{a}分間待ってやる!!";
var str2 = "時間だ!!";
var str3 = "話を聞こう!!";
var str4 = "{str2}{str3}";
println("{str1}{str4}"); // 3分間待ってやる!!時間だ!!話を聞こう!!

文字列の加算は出来ないが、クォートの中で{変数名}で結合できる

printf()的なフォーマット指定するやつ

Javaの場合

double m = 3.14;
System.out.printf("%1.5f" , m);   //3.14000

JavaFXの場合

var m = 3.14;
println("{%1.5f m}");  //3.14000

printf()は用意されてないけど、println()で出来る。
というかStringに用意されていると言った方が正しいのか
{フォーマット (スペース) 変数名}で指定する

var str = "{%1.5f 3.14}";
println(str);    //3.14000
キャスト

Javaの場合

double m = 3.14;
int i = (int)m;          //3

JavaFXの場合

var m = 3.14;
var i : Integer = m as Integer;      //3

as演算子を使う
むしろJavaFXでは数字もオブジェクトなので、intValue()とかdoubleValue()というメソッドを呼ぶことで変換できる

var i : Integer = 3.14.intValue();      //3
剰余演算

Javaの場合

int i = 17 % 3;

JavaFXの場合

var i = 17 mod 3;

%ではなくmodを使う

論理演算

Javaの場合

boolean b = true;
System.out.println(!b);     //false

JavaFXの場合

var b : Boolean = true;
println("{not b}");     //false

!ではなくnotを使う

クラスの生成

Javaの場合

class Musuka {
  private String name;
  Musuka(String name) {
    this.name = name;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}
class Main() {
  Main(){
    Musuka msk = new Musuka("ムスカ大佐");
    msk.setName("ロムスカ・パロ・ウル・ラピュタ");
    String name = msk.getName();
  }
  //..以下略
}

JavaFXの場合

class Musuka {
  var name : String;
  public function getName() : String {
    return name;
  }
  public function setName(name  : String) : Void {
    this.name = name;
  }
}
var msk = Musuka {
  name : "ムスカ大佐"
};
msk.setName("ロムスカ・パロ・ウル・ラピュタ");
var name = msk.getName();

オブジェクト生成は

(クラス名) {
    (変数名) : (初期化)
    (変数名) : (初期化)
    ...
}

と書く。
functionはメソッド定義(関数)
実はreturn文を書かなくても自動的に最後の計算式が返り値になる
クラス内だけでなくC言語のようにどこでも定義できる。
あと、voidの戻り値はVoidと書かないといけない

コマンド引数を使う場合

Javaの場合

class Main() {
  public static void main(String[] args) {
    for(String str : args) {
        System.out.println(str);
    }
  }
}

JavaFXの場合

function run(args: String[]) {
  for(str in args){
    println(str);
  }
}

main()ではなくrun()が用意されている
これを使うと今までみたいに自由な位置でprintln()したりできなくなる(普通のJavaみたいな書き方にすればよい)
for文はforeachのみ書ける。:ではなくinを使う

配列(シーケンス)

Javaの場合

int[] arr = new int[]{1,2,3,4,5};
int[] arr2 = new int[arr.length];
for( int i = 0; i < arr.length; ++i ){
  arr2[i] = arr[i] * 2;
}
System.out.println(java.util.Arrays.toString(arr2));    //[2, 4, 6, 8, 10]

JavaFXの場合

var arr = [1..5];
var arr2 = for( i in arr ) { i * 2 };
println(arr2)    //[ 2, 4, 6, 8, 10 ]

ここはかなりLLチックな構文になっている!
特に2行目のfor文が配列に化すところに注目
他にも配列のスライスとかもあるんだけど、今回は書かない

for文

Javaの場合

int[][] arr = new int[10][10];
for(int i = 0; i < 10; i++){
  for(int j = 0; j < 10; j++){
      arr[i][j] = 1;
  }
}
int[] arr2 = new int[]{1,2,5,7,9,12,15,16,18};
for(int i : arr2){
  if( i % 2 == 0 ){
    System.out.println(i);
  }
}
/*
2
12
16
18
*/

JavaFXの場合

var arr =  for( i in [0..10] , j in [0..10] ){ 1 };  //多次元配列は扱えないので一次元配列になる

var arr2 = [1,2,5,7,9,12,15,16,18];
for( i in arr2 where i mod 2 == 0) {
    println(i);
}
/*
2
12
16
18
*/

二重for文はPythonみたいに一行で書けるのと、for文にwhereで条件が書ける

nullの扱い

Javaの場合

Object o = null;
int[] a = new int[]{}; 
System.out.println( o == null );  //true
System.out.println( a == null );  //false
System.out.println(""==null);    // false

JavaFXの場合

var o : java.lang.Object = null;
var a : Integer[] = []; 
println( o == null );  //true
println( a == null );  //true
println(""==null);    // true

JavaFXのnullは要素が空かどうかでnullを返すので注意が必要

最後に

多すぎてGUIの部分まで行かなかった/(^o^)\
JavaFXJavaは似て非なるものだということが分かった
次はGUIをやりたい