S-JIS[2013-03-03/2014-05-14] 変更履歴

Eclipseプラグイン SWT テーブル

Eclipseプラグイン開発で扱うSWTのテーブルについて。


概要

表形式でデータを表示する。


import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
	Table table = new Table(composite,  SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);

	table.setHeaderVisible(true);	// 見出しを表示する
	table.setLinesVisible(true);	// 行間の線を表示する

	// 列の設定
	{
		TableColumn col1 = new TableColumn(table, SWT.LEFT);
		col1.setText("name");
		col1.setWidth(140);

		TableColumn col2 = new TableColumn(table, SWT.LEFT);
		col2.setText("type");
		col2.setWidth(100);

		TableColumn col3 = new TableColumn(table, SWT.LEFT);
		col3.setText("description");
		col3.setWidth(130);
	}

	// データの設定
	for (int i = 1; i <= 10; i++) {
		TableItem item = new TableItem(table, SWT.NONE);
		item.setText(0, "name" + i);
		item.setText(1, "type" + i);
		item.setText(2, "desc" + i);
	}

列毎にTableColumnを作成する。
setWidth()で幅をセットしておかないと、列が表示されない。(たぶん幅0になっている)

行毎にTableItemを作成する。


メソッド

知っておくと便利そうなメソッド。

  メソッド(使用例) 説明
new TableColumn(table, style); 新しい列を追加する。
int size = table.getColumnCount(); 列数を取得する。
TableColumn tc = table.getColumn(column);
TableColumn[] cs = table.getColumns();
TableColumnを取得する。
int column = table.indexOf(tc); 列番号を取得する。
new TableItem(table, style); 新しい行を追加する。
item.setText(column, text);
String text = item.getText(column);
データ(テキスト)を設定/取得する。
int size = table.getItemCount(); 行数を取得する。
TableItem item = table.getItem(row);
TableItem[] is =table.getItems();
TableItem(行データ)を取得する。
TableItem item = table.getItem(point); マウスイベントの座標からTableItemを取得する。→使用例
int row = table.indexOf(item); 行番号を取得する。
table.remove(row);
table.remove(start, end);
table.remove(indexArray);
行を削除する。
table.removeAll(); 全ての行を削除する。
int h = table.getItemHeight(); 行の高さを取得する。
選択 TableItem[] items = table.getSelection(); 選択された行を取得する。
int count = table.getSelectionCount(); 選択されている行数を取得する。
int n = table.getSelectionIndex();
int[] ns = table.getSelectionIndices();
選択された行の番号を取得する。
boolean b = table.isSelected(row); 行が選択されているかどうかを判定する。
table.select(row);
table.select(start, end);
table.select(indexArray);
行を選択する。
(SWTのテーブルではセル(列)を単独で選択することは出来ない)
table.selectAll(); 行を全て選択する。
table.deselect(row);
table.deselect(start, end);
table.deselect(indexArray);
行の選択を解除する。
table.deselectAll(); 全ての選択を解除する。
table.setSelection(row);
table.setSelection(start, end);
table.setSelection(indexArray);
table.setSelection(item);
行を選択する。
内部でdeselectAll()select()およびshowSelection()を呼び出している。
(異なる場所に対してselect()を複数回呼び出すと選択範囲が増えていくが、
 setSelection()では直前の選択範囲はクリアされる)
表示 table.showSelection(); 指定された箇所が見えるようにスクロールする。
(selectionだと選択された行、columnだと指定列、itemだと指定行)
table.showColumn(tc);
table.showItem(item);

行のクリック

テーブルがクリックまたはダブルクリックされたことを検知するには、SelectionListenerを使う。[2013-04-19]

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
		final Table table = 〜;

		table.addSelectionListener(new SelectionAdapter() {
			// クリック
			@Override
			public void widgetSelected(SelectionEvent e) {
				int select = table.getSelectionIndex();
				if (select < 0) {
					return;
				}
				Object data = table.getItem(select).getData();
				if (data == null) {
					return;
				}
				doClick(data);
			}
			// ダブルクリック
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				int select = table.getSelectionIndex();
				if (select < 0) {
					return;
				}
				Object data = table.getItem(select).getData();
				if (data == null) {
					return;
				}
				doDoubleClick(data);
			}
		});

なんでダブルクリックが「DefaultSelected」という名前なのかと言うと、稼働環境によってデフォルトの選択動作が異なる為らしい。
「Windowsだとダブルクリック」ということのようだ。


範囲外のクリック

SelectionListenerは、データの有る行・列をクリックした場合にしか反応しない。[2013-05-14]
テーブル内のそれ以外の場所(空行・空列)がクリックされたことを検知するには、MouseListenerを使う。

import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				Point point = new Point(e.x, e.y);

				Table table = (Table) e.getSource();
				TableItem item = table.getItem(point);
				if (item == null) {
					// 範囲外がクリックされた
				}
			}
		});

table.getItem(point)で、クリックされた位置のTableItemが取れる。
逆に言うと、取れなかった場合は範囲外がクリックされたということになる。


TableEditor

テーブルのセルをクリックした時にそのセルを編集する例。

マウスのクリックイベントを拾ってセルのエディターを作成する。

import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				Point point = new Point(e.x, e.y);

				Table table = (Table) e.getSource();
				TableItem item = table.getItem(point);
				if (item == null) {
					return;
				}
				for (int i = 0; i < table.getColumnCount(); i++) {
					if (item.getBounds(i).contains(point)) {
						createEditor(table, item, i);
						break;
					}
				}
			}
		});
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
	private void createEditor(Table table, final TableItem item, final int column) {
		final Text text = new Text(table, SWT.NONE);
		text.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				item.setText(column, text.getText());
				text.dispose(); 
			}
		});
		text.addTraverseListener(new TraverseListener() {
			@Override
			public void keyTraversed(TraverseEvent e) {
				switch (e.detail) {
				case SWT.TRAVERSE_RETURN:
					item.setText(column, text.getText()); 
					text.dispose(); 
					break;
				case SWT.TRAVERSE_ESCAPE:
					text.dispose();
					e.doit = false;
					break;
				}
			}
		});

		TableEditor editor = new TableEditor(table);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;
		editor.minimumWidth = 64;
//		editor.grabVertical = true;
		editor.setEditor(text, item, column);

		text.setText(item.getText(column));
		text.selectAll();
		text.setFocus();
	}

TableEditorを作り、そこにsetEditor()で“実際に編集を行うコンポーネント”(上記の例ではText)を登録する。
grabHorizontal(幅をセルに合わせる)をtrueにするのは超重要! これが無いと、エディターが表示されていないように見える。[2013-05-02]

TextとTableItemは直接データ連動している訳ではないので、どこかのタイミングでデータ移送する必要がある。

Textにはリスナーを2つ登録してる。
FocusListenerは、マウスをテーブル外でクリックした等でフォーカスを失ったときの処理。
TraverseListenerは、EnterキーやEscキーが押されたときの処理。(タブキーを押したときのTRAVERSE_TAB_NEXTやTRAVERSE_TAB_PREVIOUSといった値もある)


SWTへ戻る / Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま