Top / Eclipse / プラグイン開発のTIPS集 / TableViewer

TableViewer?とは

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

pic01.png

ViewPart?に配置する

ビューに配置するには、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);

とするだけです。

カラムを設定する

次に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のソースに非常に汎用的なコーディングがあったので、それに沿ってやってみたいと思います。

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を下に載せときました。

IFieldはヘッダ名やヘッダに表示するアイコンの情報、またビューワの各カラムにオブジェクトが渡されたときにオブジェクトを文字列に変換する変換処理、などを備えた(自作の*1)インタフェースです。後に出てくるので詳細は割愛します。。

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

ここまででカラムが3つあるTableViewer?が構築されました。さてこのテーブルに値を表示させていくのですが、JFaceレイヤのTableViewer?では

という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が出てきそうですが、それをポリモフィズムで何とかしてるわけです。

まとめると

TableViewer?を構築

という感じですね。

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

ソート処理

保存処理

DnD

TIP集

どのカラムをクリックしてもその行を選択状態にする

viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
               | SWT.V_SCROLL|SWT.FULL_SELECTION);

SWT.FULL_SELECTION がポイントです*2

プロパティ値を設定する。

String[] properties = new String[] { "text", "check", "color", "combo" };
// カラム・プロパティの設定
viewer.setColumnProperties(properties);

ICellModifier#getValue(Object element, String property)

のproperty値になります。

ICellModifier?などについては編集機能付きテーブルとはをご参照ください。

参考1 ColumnPixelData?JavaDoc?コメント

/**
 * 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;
}

この記事は

選択肢 投票
おもしろかった 1  
そうでもない 0  

Top / Eclipse / プラグイン開発のTIPS集 / TableViewer

現在のアクセス:35004


*1 Eclipseのinternalなインタフェースです
*2 クリックに反応して選択した行を変えようと思って、いろんなリスナを探してしまった

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