今回は、前回作成した「MonolineFunction」 MVC グループ内のコーディングを行います(一覧)。 見た感じはこんなのでした:
当面はこのグループ自体には処理を実装しないので、Controller はひとまず置いておきます。 また、この View を内部に含む「FunctionPlotter」 MVC グループも変更する必要がありますが、それは次回以降に見ていくことにして今回は触れません。
MonolineFunctionModel.groovy
まずは Model。 この Model に持たせる情報は、JFreeChart でグラフに描画できるデータを生成するのに必要な情報です。 もう少し具体的に言うと、JFreeChart で関数を表すインターフェース Function2D を通して XYSeries オブジェクトを生成するのに必要な情報です。 この情報は
プロパティ名 | 型 | 説明 |
---|---|---|
name | String | 関数名。 凡例にも使用。 |
function | String | 関数の内容を表す Groovy コード。 |
samples | int | サンプル数。 |
です。 Model のコードはこんな感じ:
package functionplotter class MonolineFunctionModel{ @Bindable String name @Bindable String function @Bindable int samples = 1000 // org.jfree.data.xy.XYSeries オブジェクトを生成するのに関連するメソッド }
簡単のため View から値を変更できるのは function プロパティのみとしますが、他のプロパティも @Bindable アノテーションを付加しています。 また、各プロパティの値の初期化は以下のようになっています(いくらか先取りしている部分もありますが):
プロパティ | 初期化方法 |
---|---|
name | MVC グループが作成される際に渡されるパラメータによって「'f(x)'」に初期化される(次回以降に見ます) |
function | 以下の MonolineFunctionView から「'sin(x)'」に初期化される |
samples | 「1000」に初期化される |
我ながらいろいろな初期化方法が出てきて満足:-) 上記のどの方法でも(さらに他の方法でも)初期化されない場合は null 値が設定されるのでしょう。
MonolineFunctionView.groovy
さて、次は View のコーディング。 View はこんな感じにするのでした:
コードはこんな感じ:
package functionplotter import net.miginfocom.swing.MigLayout panel(id:'content', border:BorderFactory.createTitledBorder('Groovy'), layout:new MigLayout()){ label text: bind(source:model, 'name') label '=' textField 'sin(x)', columns:15, text: bind(target:model, 'function') }
ちょっといくつか注意を(追記の項にもっとシンプルなコードあります)。
コンポーネントの id
コンポーネントに id を付けることで Controller などからそのコンポーネントを参照できるようになります。 例えば、上記の content で指定されるパネルに Controller からアクセスするためには
class MonolineFunctionController { def model def view def someAction = { event = null -> def content = view.content // content に対する処理 } }
とします(これは以前やりましたね)。 このような id の設定は、他にも下記のような方法があります:
content = panel(border:BorderFactory.createTitledBorder('Groovy'), layout:new MigLayout()){ ... }
Griffon に付属しているサンプルではむしろこちらの方が多く使われています。
Model のプロパティからのバインド
1つ目のラベルは関数名を表示させます。 これは Model の name プロパティの値が変更されれば、その変更をこのラベルへ反映させるようにしたいので、バインドには source を指定します:
label text: bind(source:model, 'name')
図中の矢印は「反映の方向」です。
Model のプロパティへのバインド
3つ目のテキストフィールドは関数の内容を入力させます。 これはテキストフィールドの内容を Model の function プロパティへ反映させるようにしたいので、バインドには target を指定します(これも以前もやりましたね):
textField 'sin(x)', columns:15, text: bind(target:model, 'function')
バインドに target を指定するには
bind{ model.function }
とすることも可能ですが、今の場合のこれを行うと 'sin(x)' による初期化が上手く Model に反映されませんでした。 単なるバグかな?
まぁ、ともかく「MonolineFunction」 MVC グループのコーディングはこれでひとまず終了。
追記
View 部分のコードに関してコメント(Andres Almiray 氏から!?)頂いたので、少々(というか大々的に?)修正。 修正箇所は
- BorderFactory.createTitledBorder('Groovy') → titledBorder(title: 'Groovy')
- layout:new MigLayout() → migLayout() (import 文も削除)
- bind(source:model, 'name') → bind{ model.name }
です。 コードはこんな感じ(コメント欄のコピペ):
package functionplotter panel (id: 'content', border: titledBorder(title: 'Groovy')) { migLayout() label text: bind{ model.name } label '=' textField 'sin (x)', columns: 15, text: bind (target: model, 'function') }
おぉ、スッキリ! クロージャで bind を指定できるのは source を指定する場合だそうです。 完全に勘違いしてました ^^;) 'migLayout()' で MigLayout の import 文がいらなくなるのも嬉しい。
- 作者: Andres Almiray,Danno Ferrin,James Shingler
- 出版社/メーカー: Manning Pubns Co
- 発売日: 2012/06/28
- メディア: ペーパーバック
- クリック: 8回
- この商品を含むブログ (19件) を見る