リストボックス

コンポーネント: listbox, listitem, listcell, listhead, listheader.

リストボックスはリスト中で項目を表示します。ユーザーはリストから項目を選択することができます。

最も簡単なフォーマットは以下のようです。それは1行・1選択のリストボックスです。

<listbox>
          <listitem label="Butter Pecan"/>    
          <listitem label="Chocolate Chip"/>    
          <listitem label="Raspberry Ripple"/>    
</listbox>

リストボックスには二つのモードがあります:defaultselectです。s electが使用されているなら、HTMLのSELECTタグが変わりに生成されます。

<listbox mold="select">...</listbox>

【注意】: モードがselectで、rowsが1、そして、項目が一つもマーク(選択)されていないなら、ブラウザは1番目の項目が選ばれた場合と同様にlistboxに1番目の項目を表示します。ユーザーが始めの項目を選んでしまったら、onSelectイベントは送信されません。混乱を避けるために開発者は少なくとも一項目、つまりmold=selectrows=1を選択すべきです。

ラベルのほかに、アプリケーション依存の値をsetValueメソッドを使用して項目ごとに指定できます。

マウスを使わずに入力:listbox

多数行のリストボックス

リストボックスは多数行をサポートします。ユーザーが項目を選択するとき、列全体が選ばれます。

多数行リストを指定するのに、リスト項目ごと(列)の行のようにlistcellコンポーネントを指定する必要があります。

<listbox width="200px">
          <listitem>    
                    <listcell label="George"/>        
                    <listcell label="House Painter"/>        
          </listitem>    
          <listitem>    
                    <listcell label="Mary Ellen"/>        
                    <listcell label="Candle Maker"/>        
          </listitem>    
          <listitem>    
                    <listcell label="Roger"/>        
                    <listcell label="Swashbuckler"/>        
          </listitem>    
</listbox>

行のヘッダー

listheadlistheaderを使うことで行のヘッダーを以下のように指定します[37]。ラベルに加えて、imageプロパティを使用することでヘッダーとしてイメージを指定できます。

<listbox width="200px">
          <listhead>    
                    <listheader label="Name"/>        
                    <listheader label="Occupation"/>        
          </listhead>    
...
</listbox>

行のフッター

listfootlisfooterを以下のように使用することで行のフッターを指定できます。l istheadlistfootの順番は問題になりません。listheadのインスタンスはリストボックスへ追加されます。それは一番目の子要素でなければなりません。また、listfootインスタンスの場合は、最後の子要素でなければなりません。

<listbox width="200px">
          <listhead>    
                    <listheader label="Population"/>        
                    <listheader align="right" label="%"/>        
          </listhead>    
          <listitem id="a" value="A">    
                    <listcell label="A. Graduate"/>        
                    <listcell label="20%"/>        
          </listitem>    
          <listitem id="b" value="B">    
                    <listcell label="B. College"/>        
                    <listcell label="23%"/>        
          </listitem>    
          <listitem id="c" value="C">    
                    <listcell label="C. High School"/>        
                    <listcell label="40%"/>        
          </listitem>    
          <listitem id="d" value="D">    
                    <listcell label="D. Others"/>        
                    <listcell label="17%"/>        
          </listitem>    
          <listfoot>    
                    <listfooter label="More or less"/>        
                    <listfooter label="100%"/>        
          </listfoot>    
</listbox>

ドロップダウンリスト

select型と一つの列を指定することでドロップダウンリストを作成することができます。ドロップダウンリストへ多数行は使用できません。

<listbox mold="select" rows="1">
          <listitem label="Car"/>    
          <listitem label="Taxi"/>    
          <listitem label="Bus" selected="true"/>    
          <listitem label="Train"/>    
</listbox>

複数選択

ユーザーがリスト項目をクリックしたとき、項目全体が選択されます。そして、onSelectイベントはサーバーに送り返されて、アプリケーションに通知します。リストボックスがmultipleプロパティにt rueを設定することで多数の選択が可能になります。デフォルトの値はfalseです。

スクロール可能なリストボックス

rowsプロパティ又はheightプロパティを指定し、リスト項目がその長さを超えれば、リストボックスはスクロール可能になります。

<listbox width="250px" rows="4">
          <listhead>    
                    <listheader label="Name" sort="auto"/>        
                    <listheader label="Gender" sort="auto"/>        
          </listhead>    
          <listitem>    
                    <listcell label="Mary"/>        
                    <listcell label="FEMALE"/>        
          </listitem>    
          <listitem>    
                    <listcell label="John"/>        
                    <listcell label="MALE"/>        
          </listitem>    
          <listitem>    
                    <listcell label="Jane"/>        
                    <listcell label="FEMALE"/>        
          </listitem>    
          <listitem>    
                    <listcell label="Henry"/>        
                    <listcell label="MALE"/>        
          </listitem>    
          <listitem>    
                    <listcell label="Michelle"/>        
                    <listcell label="FEMALE"/>        
          </listitem>    
</listbox>

rowsプロパティ

rowsプロパティは参照可能なrows(列)の数を設定します。ゼロに設定することより、リストボックスはそれ自身のサイズを変更し、可能な限り項目数に対応します。

サイズ変更可能なリストヘッダー

columnsのように、listheadsizableプロパティをt rueに設定することでリストヘッダの幅を変更可能にします。同様にして、onColSizeイベントはユーザーが幅をサイズ変更したときに送信されます。

ページングを伴ったリストボックス

グリッドのように、多数ページを使用し、ページングの型を指定することで、長いコンテンツをリストボックスに表示します。同様にして、ページごとにいくつの項目を表示するか、ページ選択時の動作をカスタマイズするかどうかを決定できます。より詳しくは、Gridsセクションを参照してください。

ソーティング

リストボックスは直接リスト項目をソーティングすることをサポートします。特定の行のソーティングを可能にする方法はいくつかあります。一番簡単な方法は以下のようにautoにリストヘッダーのsortプロパティを設定することです。リストヘッダーに関連している行は指定された行のリストセルごとのラベルを基にしてソート可能です。

<zk>
          <listbox width="200px">    
                    <listhead>        
                              <listheader label="name" sort="auto"/>            
                              <listheader label="gender" sort="auto"/>            
                    </listhead>        
                    <listitem>        
                              <listcell label="Mary"/>            
                              <listcell label="FEMALE"/>            
                    </listitem>        
                    <listitem>        
                              <listcell label="John"/>            
                              <listcell label="MALE"/>            
                    </listitem>        
                    <listitem>        
                              <listcell label="Jane"/>            
                              <listcell label="FEMALE"/>            
                    </listitem>        
                    <listitem>        
                              <listcell label="Henry"/>            
                              <listcell label="MALE"/>            
                    </listitem>        
                  </listbox>            
</zk>

sortAscendingsortDescendingプロパティ

異なった方法でリスト項目をソートするなら、java.util.ComparatorインスタンスをsortAscendingsortDescendingプロパティの両方又はどちらかに指定します。一度指定すると、リスト項目はascendingdescendingの両方か、又はどちらかに指定したコンペアレーターを使用して記憶されます。

a utoを伴ったsortプロパティの起動は自動的にsortAscendingsortDescendingに二つのコンペアレーターを指定します。それに他のコンペアレーターを指定することでオーバーライドできます。

例えば、リストセルのラベルではなくて、リスト項目の値を基にしてソートすることを想定します。以下のように、listitemComparatorのインスタンスをこれらのプロパティに指定します。

<zscript>
          Comparator asc = new ListitemComarator(-1, true, true);    
          Comparator dsc = new ListitemComarator(-1, false, true);    
</zscript>
<listbox>
          <listhead>    
                    <listheader sortAscending="${asc}" sortDescending="${dsc}"/>        
...

sortDirectionプロパティ

sortDirectionプロパティはクライアントで特定の行の列の項目を表示するかどうかを決めます。リスト項目がリストボックスに追加される前に記録されるなら、このプロパティを確実に設定すべきです。

<listheader sortDirection="ascending"/>

そのため、リストヘッダーにコンペアレーターを指定する限り、リストボックスに自動的に保存されます。

onSortイベント

リストヘッダーに少なくとも一つコンペアレーターを指定するとき、ユーザーがクリックした場合、onSortイベントがサーバーへ送信されます。リストヘッダーはリスナを実装して、ソーティングを自動的に操作します。

手動で制御するなら、onSortイベントが送信されるときのためにリストヘッダーにリスナを追加できます。デフォルトリスナにsortメソッドを呼び出させないために、イベントが受信されたときのためにstopPropagationメソッドを呼び出さなければなりません。代わりに、以下に示すようにsortメソッドをオーバーライドできます。

sortメソッド

sortメソッドはデフォルトのonSortイベントリスナ用の実装です。Javaコードでリスト項目をソートしたい場合に便利です。例えば、項目が追加された後に(適切な順番で無い場合を想定します)このメソッドを呼び出します。

new Listem("New Stuff").setParent(listbox);
if (!"natural".header.getSortDirection())
          header.sort("ascending".equals(header.getSortDirection()));    

デフォルトのソーティングアルゴリズムはquick-sortです(org.zkoss.zk.ui.Componentsクラスのsortメソッドを使用します)。自身の実装でオーバーライドまたは前のセクションで説明したようにonSortイベントを監視することができます。

【ヒント】: 多量なライブデータのソーティングはパフォーマンスを著しく低下させるかもしれません。onSortイベント、又はsortメソッドを中断し、効率的に処理させるほうがいいでしょう。以下のSort Live Dataセクションをご覧ください。

特別なプロパティ

checkmarkプロパティ

checkmarkプロパティはそれぞれの項目の前にあるcheckbox又はradioボタン表示させるかどうかを決めます。

以下の例中で、左のリストボックスから右のリストボックスへと項目を移動させたとき、どのようにcheckboxが自動的に追加されるかわかると思います。checkboxは右から左へ移動するときに外れます。

<hbox>
          <listbox id="src" rows="0" multiple="true" width="200px">    
                    <listhead>        
                              <listheader label="Population"/>            
                              <listheader label="Percentage"/>            
                    </listhead>        
                    <listitem id="a" value="A">        
                              <listcell label="A. Graduate"/>            
                              <listcell label="20%"/>            
                    </listitem>        
                    <listitem id="b" value="B">        
                              <listcell label="B. College"/>            
                              <listcell label="23%"/>            
                    </listitem>        
                    <listitem id="c" value="C">        
                              <listcell label="C. High School"/>            
                              <listcell label="40%"/>            
                    </listitem>        
                    <listitem id="d" value="D">        
                              <listcell label="D. Others"/>            
                              <listcell label="17%"/>            
                    </listitem>        
          </listbox>    
          <vbox>    
                    <button label="=&gt;" onClick="move(src, dst)"/>        
                    <button label="&lt;=" onClick="move(dst, src)"/>        
          </vbox>    
          <listbox id="dst" checkmark="true" rows="0" multiple="true" width="200px">    
                    <listhead>        
                              <listheader label="Population"/>            
                              <listheader label="Percentage"/>            
                    </listhead>        
                    <listitem id="e" value="E">        
                              <listcell label="E. Supermen"/>            
                              <listcell label="21%"/>            
                    </listitem>        
          </listbox>    
          <zscript>    
void move(Listbox src, Listbox dst) {
          Listitem s = src.getSelectedItem();    
          if (s == null)    
                    Messagebox.show("Select an item first");        
          else    
                    s.setParent(dst);        
}
          </zscript>    
</hbox>

右に表示されているように、multipleプロパティがfalseなら、radioボタンが代わりに表示されます。

vflexプロパティ

vflexプロパティは与えられたスペースに合うように縦方向の伸縮を調節します。いわゆる縦方向の柔軟性です。例えば、リストがブラウザウィンドウ中ではあまりに大きいばあい、ブラウザウィンドウ中で、高さを縮ませてリスト全体を参照できるようにします。

このプロパティはrowsプロパティが指定されていた場合無視されます。

maxlengthプロパティ

maxlengthプロパティはブラウザにて表示する最大の文字数を定義します。このプロパティを設定することで、リストボックスを狭くできます。

ライブデータ

グリッド[38]のようにリストボックスはライブデータをサポートしています。ライブデータを使うと、開発者はビューからデータを分けます。つまり開発者の仕事は、直接リストボックスを処理することより、むしろorg.zkoss.zul.ListModelインターフェースを実装することによる、データ供給だけが必要となります。利点は2つあります。

  • 簡単に異なったビューで同じデータセットを表示することができます。

  • グリッドはデータを参照可能な(visible)場合にのみクライアントに送信します。データ量が大きい場合にネットワークの通信量が増えることを防ぎます。

ライブデータを使用する三つのステップがあります。

  1. ListModelのフォーム中でデータを準備します。ZKではオブジェクト群を表示するためにorg.zkoss.zul.SimpleListModelと呼ばれる具体的な実装があります。

  2. データの項目をレンダリングしリストボックスのリスト項目へ表示するためにorg.zkoss.zul.ListitemRendererインターフェースを実装します。

  3. modelプロパティ中にデータを指定します。選択的に、itemRendererプロパティにレンダ装置を指定します。

また、ステップ2は、以下の二項目に分かれています。

  • これは指定するか選択できます、指定されていないなら、デフォルトのレンダー装置はデータを読み込み、最初の行へ入れます。

  • 異なったビューの中では同じデータをあらわすのに、異なったレンダ装置を実装できます。

以下の例ではstrsetと呼ばれるリストモデルを準備しますmodelプロパティを通してそれをリストボックスに指定します。そのため、リストボックスは残りの作業を全部代わりに実行してくれます。

<window title="Livedata Demo" border="normal">
   <zscript>
      String[] data = new String[30];
      for(int j=0; j &lt; data.length; ++j) {
         data[j] = "option "+j;
      }
      ListModel strset = new SimpleListModel(data);
   </zscript>
   <listbox width="200px" rows="10" model="${strset}">
      <listhead>
         <listheader label="Load on demend"/>
      </listhead>
   </listbox>
</window>

ライブデータを使用したソーティング

ライブデータが使用できるリストボックスをソート可能にするなら、org.zkoss.zul.ListModelに加えて、org.zkoss.zul.ListModelExtインターフェースを実装しなければなりません。

class MyListModel implements ListModel, ListModelExt {
          public void sort(Comparator cmpr, boolean ascending) {    
                    //do the real sorting        
                    //notify the listbox (or grid) that data is changed by use of ListDataEvent        
          }    
}

ユーザーがリストボックスにソート要求するとき、リストボックスはListModelExtsortメソッドを呼び出し、データをソートします。リストボックスよりむしろ、リストモデルによってソーティングは行われます。

ソート後は、(addListDataListenerメソッドにより) リストボックスに記憶されたorg.zkoss.zul.event.ListDataListenerインスタンスのonChangeメソッドを呼び出すことより、リストモデルはリストボックスに通知します。ほとんどの場合全データはたいてい変更され、リストモデルは以下のイベントを送信します。

new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1)

メモ:ListModelListModelExtの実装は視覚表現に依存しません。つまり、グリッド、リストボックス、ListModelをサポートしている他のコンポーネントと共にそれらは使用されます。

つまり、柔軟性を高めるにはコンポーネントを使用することは想定すべきではないです。むしろ、ListDataEventを使用して通信します。

ボタンを含むリストボックス

理論ではリストセルは以下に示すように、他のどのコンポーネントも含むことができます。

<listbox width="250px">
   <listhead>
      <listheader label="Population"/>
      <listheader label="Percentage"/>
   </listhead>
   <listitem value="A">
      <listcell><textbox value="A. Graduate"/></listcell>
      <listcell label="20%"/>
   </listitem>
   <listitem value="B">
      <listcell><checkbox label="B. College"/></listcell>
      <listcell><button label="23%"/></listcell>
   </listitem>
   <listitem value="C">
      <listcell label="C. High School"/>
      <listcell><textbox cols="8" value="40%"/></listcell>
   </listitem>
</listbox>

【メモ】:

  1. グリッドがより適切の場合では、リストボックスの使用を避けましょう。リストボックスとグリッドの外見は似ていますが、リストボックスは選択できる項目をあらわすときのみに使用するべきです。

  2. リストボックスが編集可能なtextboxcheckboxといったコンポーネントを含んでいる場合、ユーザーは混乱します。たとえば選択されていない項目に入力されたテキストの意味がわからなくなります。

  3. ブラウザの制限によって、ユーザーはテキストボックス中の文字列を選択できない場合があります。



[37] この機能はlisthead 、listheaderを使用するかについて、XULとは少し異なります。

[38] Swing (javax.swing.ListModel)のコンセプトと類似しています。