ダイナミックなデータのバインド
<grid>のように、多くのデータを扱うコンポーネントの場合、最初から静的にデータを持たせることの方が少ないでしょう。データの追加や削除を自由に行うことができないと困るので、必要に応じてダイナミックに表示データを扱えるようにしなければ実用的とは言えません。
これにはいくつかの方法があるのですが、今回の例のように複数の列を持つデータの場合、データの構造とレンダリング方法をそれぞれ<grid>が理解できなければ正しくデータを扱うことができません。
<grid>には、「model」と「rowRenderer」という属性が用意されています。前者は表示するデータのモデルで、これはListModelというインターフェイスを実装したクラスを用意して使います。またrowRendererは行のレンダリングを行うためのもので、これはRowRendererというインターフェイスを実装したクラスを用意します。では、実際にやってみましょう。
<?page title="Index Page"?> <zk> <zscript> class SampleRowData { private String name; private String mail; private String tel; public SampleRowData(String s1,String s2,String s3){ name = s1; mail = s2; tel = s3; } public String getName(){ return name; } public void setName(String s){ name = s; } public String getMail(){ return mail; } public void setMail(String s){ mail = s; } public String getTel(){ return tel; } public void setTel(String s){ tel = s; } } class SampleRowRenderer implements RowRenderer { public void render(Row row, java.lang.Object obj){ SampleRowData data = (SampleRowData)obj; new Label(data.getName()).setParent(row); new Label(data.getMail()).setParent(row); new Label(data.getTel()).setParent(row); } } // モデルとレンダラーの作成 ListModelList modellist = new ListModelList(new ArrayList()); modellist.add(new SampleRowData("つやの","tuyano@mac.com","090-9999-9999")); modellist.add(new SampleRowData("太郎","taro@yamada.com","080-8888-8888")); modellist.add(new SampleRowData("花子","hanako@tanaka.com","070-7777-7777")); modellist.add(new SampleRowData("イチロー","ichiro@suzuki.com","060-6666-6666")); modellist.add(new SampleRowData("サチコ","sachi@ko.com","050-5555-5555")); SampleRowRenderer renderer = new SampleRowRenderer(); </zscript> <window title="Welcome to ZK!" border="normal" width="500px"> <label>※入力フォームのレイアウト</label> <separator /> <grid width="90%" model="${modellist}" rowRenderer="${renderer}"> <columns sizable="true"> <column label="名前" /> <column label="メールアドレス" /> <column label="電話番号" /> </columns> </grid> <separator /><separator /> </window> </zk>
ここでは、表示データを管理する「SampleRowData」というクラスを用意し、これを「ListModelList」というモデル用クラスに組み込みモデルとして利用しています。またSampleRowRendererというレンダラークラスを用意し、これでSampleRowDataの表示を行わせています。
まず、モデルから見ていきましょう。今回は、名前・メールアドレス・電話番号といったものを扱いますので、これらの値をプロパティにもつSampleRowDataクラスを定義しています。そして、リストのモデル(ListModel)を管理するListModelListというクラスを作成し、SampleRowDataを組み込んでいきます。
ListModelList modellist = new ListModelList(new ArrayList()); modellist.add(new SampleRowData("つやの","tuyano@mac.com","090-9999-9999")); ……以下略……
ListModelListは、モデルであるListModelと、多数のデータを管理するためのListインターフェイスを実装しています。つまり、ListModelとして扱えると同時に、Listとして保管データの管理を行うことだできるようになっているのです。インスタンス作成時に、データ保管用のArrayListを引数に渡しておき、以後、addメソッドでデータを追加しています。
続いて、レンダラーです。レンダラーは、RowRendererインターフェイスを継承します。これは「render」というメソッドをもっており、ここでデータ表示の際のレンダリング処理を行ないます。メソッドでは、引数として表示する行のRowインスタンスと、表示データ(ここではSampleRowDataインスタンス)が渡されます。表示データのオブジェクトから必要な値を取得し、それをもとに表示する内容を生成していくわけです。ここでは取り出したデータを、以下のようにしてRowに組み込んでいます。
new Label(表示データ).setParent(row);
Labelインスタンスを作成し、その「setParent」を呼び出しています。これは、このコンポーネントが組み込まれる親を設定するもので、引数にrowを指定することで、このrow内にLabelが組み込まれることになります。こうして必要なデータを元にLabelを作成し、すべてrowに組み込むことで、データの表示を作成しているのです。
ListModel(ここではListModelListですが)を利用することで、データをダイナミックに操作することができるようになります。また、必要に応じてデータを取得し表示すれば良いため、元データがデータベースにあろうがテキストファイルであろうが、関係なく表示に利用できるようになります。
まとめ
今回は、コンポーネント類をまとめるコンテナ関係と、データを扱うためのコンポーネントを中心に説明しました。前回と今回で、ZKに用意されている主なコンポーネント類については一通り理解できたのではないでしょうか。このほかに、ツリー表示やメニュー関係などがまだ残っていますが、基本的なGUIはこれで大抵作れるようになったはずです。
コンテナやデータ表示のためのコンポーネントというのは、タグだけでなく、処理の部分が多くなりがちです。しかし、ZKでは、なるべくタグだけで済むようにし、極力コードを書かずにGUIが構築できるよう設計されていることがよく分かります。例えば、表関係では横幅の調整などまで属性の設定だけで行うことができるようにしていたり、配列を元にデータを表示する場合もforEach属性で必要最小限のコードで済むようになっています。
またコードを記述する際も、Java本来のコーディングであれば常にクラスを定義するところから始まりますが、グローバル関数の利用などによりなるべくシンプルなコードで済むようになっています。
ZKはJavaベースとはいえ、各種言語でコードを記述できますから、これを「Javaのフレームワークである」と言い切ってしまう方が無理があります。「Javaも使える、スクリプト言語ベースのフレームワーク」と割り切り、気軽に利用するのが賢い使い方なのでしょう。