JavaFX データバインディング

お次はデータバインディングについて。

データバインディングするためには、そもそもバインドするためのデータが必要になる。プリミティブな型ではつまらないので新しい型を定義する。

クラスの定義

JavaFXでのクラス定義の方法はすごく簡単で以下のようにする。

class Person {
   attribute firstname:String;
   attribute lastname:String;
   operation fullname():String;
}

operation Person.fullname() {
   return "{firstname} {lastname}";
}

「class クラス名」で宣言して、中括弧で囲った中にクラスの定義を記述する。

属性は「attribute 属性名:型名」という形で宣言する。てっきり型が省略できるかと思っていたけど、省略したらエラーが出た。このへんは厳格。

関数は「operation 関数名(引数リスト):型名」という形で宣言する。クラス定義の中には宣言だけで、関数の実体は別途記述する必要がある。関数本体ではreturn文でfirstnameとlastnameを連結して返している。「{属性名}」と属性名を中括弧で囲むとプレースホルダーとなり変数の値が展開される。

データバインディング

では、データバインディングをやってみる。バインディング自体は簡単で「bind 属性名」という形でUIコントロールの属性に設定するだけ。

databinding.fx

import javafx.ui.*;

class Person {
   attribute firstname:String;
   attribute lastname:String;
   operation fullname():String;
}

operation Person.fullname() {
   return "{firstname} {lastname}";
}

var data = [
   Person { firstname:"ポール", lastname:"ギルバート" },
   Person { firstname:"ジョン", lastname:"サイクス" },
   Person { firstname:"クリス", lastname:"インペリテリ" }
];

var window = Frame {
   title:"Data Binding"
   width:300
   height:250
   screenx:200
   screeny:200
   content:BorderPanel {
       center:ListBox {
           cells:foreach(o in data) ListCell {
               text:bind o.firstname
           }
       }
       bottom:Button {
           text:"Push me!!"
           action:operation() {
               for(o in data) { o.firstname = "Hoge"; }
           }
       }
   }
   visible:true
};

これを実行すると以下のウィンドウが表示される。

ボタンをクリックするとデータが変更された画面に反映される。

解説
var data = [
   Person { firstname:"ポール", lastname:"ギルバート" },
   Person { firstname:"ジョン", lastname:"サイクス" },
   Person { firstname:"クリス", lastname:"インペリテリ" }
];

まずPerson型をインスタンス化し、配列にセットしている。

center:ListBox {
  cells:foreach(o in data) ListCell {
      text:bind o.firstname
  }
}

ListBoxのcells属性にdataの要素数だけListCellを生成している。ListCellのtext属性にfirstname属性をバインドしている。

JavaFXのforeachステートメントは他の言語のそれとは違い、最後の文の結果を返す。配列の変換演算子のように機能する。

action:operation() {
   for(o in data) { o.firstname = "Hoge"; }
}

対して、こっちのforは普通の繰り返し文。

ちょっとおもしろくなってきた。