#topicpath
----
//ここにコンテンツを記述します。
#contents

**TableViewerとは [#vff32b94]
TableViewerとは、JFaceのレイヤが提供するビューワクラスです。いわゆる表形式のデータを表示するために使用するウィジェットです。SWTのTableクラスのラッパになっていて、データを表示する機能やDrag&Dropやソート機構など、いろいろ便利な機能を提供してくれます。


#ref(pic01.png)

***ViewPartに配置する [#if260bfa]
ビューに配置するには、ViewpartのcreatePartControl(Compsite parent)内で
 Composite container = new Composite(parent, SWT.NONE);
 container.setLayout(new FillLayout());
 viewer = new TableViewer(container, SWT.FULL_SELECTION | SWT.BORDER
                | SWT.H_SCROLL | SWT.V_SCROLL);
とするだけです。

***カラムを設定する [#tb127cc2]
次にTableViewerにカラム(列)を定義していきます。基本的にTableViewerからSWTのTableクラスを取得して
 table = viewer.getTable();
 TableColumn tc1 = new TableColumn(table, SWT.NONE, 0);
 TableColumn tc2 = new TableColumn(table, SWT.NONE, 1);
としていけばよいのですが、Eclipseの[[TaskView:http://www.kickjava.com/src/org/eclipse/ui/views/markers/internal/TaskView.java.htm]]のソースに非常に汎用的なコーディングがあったので、それに沿ってやってみたいと思います。


ViewPartのフィールドに定義
 private final ColumnPixelData[] DEFAULT_COLUMN_LAYOUTS = {
     new ColumnPixelData(200), new ColumnPixelData(200),
     new ColumnPixelData(200) };
 private final IField[] VISIBLE_FIELDS = { new TitleField(),
     new SummaryField(), new URLField() };

ColumnPixelDataはそのカラムがリサイズ可能かとか、大きさはいくつかなどの情報を指定します。ちなみに[[ColumnPixelDataのJavaDocを下に載せときました。>Eclipse/プラグイン開発のTIPS集/TableViewer#e1b3d231]]

IFieldはヘッダ名やヘッダに表示するアイコンの情報、またビューワの各カラムにオブジェクトが渡されたときにオブジェクトを文字列に変換する変換処理、などを備えた(自作の((Eclipseのinternalなインタフェースです)))インタフェースです。後に出てくるので詳細は割愛します。。
 public interface IField {
   String getColumnHeaderText();
   Image getColumnHeaderImage();
   String getValue(Object obj);
   Image getImage(Object obj);
 }
これを各カラムに沿った形でOverrideすればOKです。


次に ViewPart#createPartControlで以下のように記述します。
 table = viewer.getTable();
 TableLayout layout = new TableLayout();
 table.setLayout(layout);
 table.setHeaderVisible(true); // ヘッダは表示する
 table.setLinesVisible(true);  // ラインは表示する
 
 ColumnLayoutData[] columnLayouts = getColumnLayouts();
 
 for (int i = 0; i < columnLayouts.length; i++) {
   layout.addColumnData(columnLayouts[i]);
   TableColumn tc = new TableColumn(table, SWT.NONE, i);
   tc.setText(VISIBLE_FIELDS[i].getColumnHeaderText());
   tc.setImage(VISIBLE_FIELDS[i].getColumnHeaderImage());
 }

 private ColumnLayoutData[] getColumnLayouts() {
   ColumnPixelData[] result = new ColumnPixelData[DEFAULT_COLUMN_LAYOUTS.length];
   for (int i = 0; i < DEFAULT_COLUMN_LAYOUTS.length; i++) {
     int width = DEFAULT_COLUMN_LAYOUTS[i].width;
     //////////// ※ /////////////////
     result[i] = new ColumnPixelData(width);
   }
   return result;
 }

これでTableにTableColumnがセットされました。getColumnLayoutsについてですが、なかで新しいColumnPixelDataを作成して、んで配列ColumnPixelData[]を返しています。このままだとフィールドと同じモノが返るのでわけわかんないのですが、実は※のところに処理があります。いまんところは、あまり気にせずにいきましょう。後述します。


***ドメインオブジェクトと2つのProvider [#pbf78763]
ここまででカラムが3つあるTableViewerが構築されました。さてこのテーブルに値を表示させていくのですが、JFaceレイヤのTableViewerでは
-表示したいデータを持つドメインオブジェクト
-ドメインオブジェクトとTableViewerの橋渡しをするContentProvider
-TableViewerに値を表示するためのLabelProvider

という3種類のオブジェクトが重要です。

たとえば、ドメインオブジェクトを
 public intarface Model{
   getSummary();
   getURL();
   getTitle();
 }
とします。このオブジェクトがたとえば10個(たとえば配列models)あったときに、それをTableViewerで一行に一オブジェクト表示したいときは、直接TableViewer#setInput(models);としてしまえばOKです。後は二つのプロバイダが何とかしてくれます。

ContentProviderについてですが、実はドメインオブジェクトが配列やListの場合に関しては、JFaceでArrayContentProviderというプロバイダを提供してくれています。よってcreatePartControlで
  viewer.setContentProvider(new ArrayContentProvider());
で終わりです。これで各行に一つのModelオブジェクトを割り当ててくれます。


つぎにLabelProviderです。LabelProviderはContentProviderが各行に割り当ててくれたオブジェクト(Modelでした)を、各カラムになんと表示するか指定します。

以下のように定義しました。
 class ViewLabelProvider extends LabelProvider implements
     ITableLabelProvider {
   private final IField[] fields;
   public ViewLabelProvider(IField[] fields) {
     this.fields = fields;
   }↑ViewPartに定義したIFieldです
 
   public String getColumnText(Object obj, int index) {
     if (obj instanceof Model) { ↑indexは左から何番目のカラムか
        ↑ ContentProviderが配列から取り出して渡してくれる
       Modelelement = (Model) obj;
       return fields[index].getValue(element);
     }
     return "";
   }
 
   public Image getColumnImage(Object element, int columnIndex) {
     return null; <-イメージを使いたい場合には何かを返す
   }
 }
このクラスを作っておいて、
 viewer.setLabelProvider(new ViewLabelProvider(VISIBLE_FIELDS));
としておけばOKです。

IFieldの効能についてですが、このようなクラスがないとLabelProviderの中で、一列目だったらmodel#getTitle,二列目だったらmodel#getSummaryなどとswitchが出てきそうですが、それをポリモフィズムで何とかしてるわけです。


まとめると
-フィールドの
 ColumnPixelData[] DEFAULT_COLUMN_LAYOUTS;
 IField[] VISIBLE_FIELDS;

でTableViewerを構築
-TableViewerの行単位のデータを生成するContentProviderを定義(ArrayContentProviderで十分の場合もある)
-行単位のデータを実際に各カラムに表示するためのLabelProviderを定義。その中でIFieldを有効に使う

という感じですね。

参考~
[[プラグイン開発のTIPS集/GooglePlugin/検索結果一覧を表示するビューの作成>Eclipse/プラグイン開発のTIPS集/GooglePlugin/検索結果一覧を表示するビューの作成]]






***ソート処理 [#fb034da8]
***保存処理 [#kf99e51e]
***DnD [#g8954bdb]



**TIP集 [#lb5222ff]
***どのカラムをクリックしてもその行を選択状態にする [#lee5a252]
 viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
                | SWT.V_SCROLL|SWT.FULL_SELECTION);

SWT.FULL_SELECTION がポイントです((クリックに反応して選択した行を変えようと思って、いろんなリスナを探してしまった))。


***プロパティ値を設定する。 [#nc785d79]
 String[] properties = new String[] { "text", "check", "color", "combo" };
 // カラム・プロパティの設定
 viewer.setColumnProperties(properties);
は
 ICellModifier#getValue(Object element, String property)
のproperty値になります。

ICellModifierなどについては[[編集機能付きテーブルとは>Eclipse/プラグイン開発のTIPS集/編集機能付きテーブル]]をご参照ください。


***参考1 ColumnPixelDataのJavaDocコメント [#e1b3d231]
 /**
  * Creates a resizable column width of the given number of pixels.
  *
  * @param widthInPixels the width of column in pixels
  */
 public ColumnPixelData(int widthInPixels) {
   this(widthInPixels, true, false);
 }
 
 /**
  * Creates a column width of the given number of pixels.
  *
  * @param widthInPixels the width of column in pixels
  * @param resizable <code>true</code> if the column is resizable,
  *   and <code>false</code> if size of the column is fixed
  */
 public ColumnPixelData(int widthInPixels, boolean resizable) {
 this(widthInPixels, resizable, false);
 }
 
 /**
  * Creates a column width of the given number of pixels.
  * 
  * @param widthInPixels
  *      the width of column in pixels
  * @param resizable
  *      <code>true</code> if the column is resizable, and
  *      <code>false</code> if size of the column is fixed
  * @param addTrim
  *      <code>true</code> to allocate extra width to the column to
  *      account for trim taken by the column itself,
  *      <code>false</code> to use the given width exactly
  * @since 3.1
  */
 public ColumnPixelData(int widthInPixels, boolean resizable, boolean addTrim) {
   super(resizable);
   Assert.isTrue(widthInPixels >= 0);
   this.width = widthInPixels;
 this.addTrim = addTrim;
 }
----
この記事は
#vote(おもしろかった[1],そうでもない[0])

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS