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を取得する。 | |
int column = table.indexOf(tc); |
列番号を取得する。 | |
| 行 | new TableItem(table, style); |
新しい行を追加する。 |
item.setText(column, text); |
データ(テキスト)を設定/取得する。 | |
int size = table.getItemCount(); |
行数を取得する。 | |
TableItem item = table.getItem(row); |
TableItem(行データ)を取得する。 | |
TableItem item = table.getItem(point); |
マウスイベントの座標からTableItemを取得する。→使用例 | |
int row = table.indexOf(item); |
行番号を取得する。 | |
table.remove(row); |
行を削除する。 | |
table.removeAll(); |
全ての行を削除する。 | |
int h = table.getItemHeight(); |
行の高さを取得する。 | |
| 選択 | TableItem[] items = table.getSelection(); |
選択された行を取得する。 |
int count = table.getSelectionCount(); |
選択されている行数を取得する。 | |
int n = table.getSelectionIndex(); |
選択された行の番号を取得する。 | |
boolean b = table.isSelected(row); |
行が選択されているかどうかを判定する。 | |
table.select(row); |
行を選択する。 (SWTのテーブルではセル(列)を単独で選択することは出来ない) |
|
table.selectAll(); |
行を全て選択する。 | |
table.deselect(row); |
行の選択を解除する。 | |
table.deselectAll(); |
全ての選択を解除する。 | |
table.setSelection(row); |
行を選択する。 内部で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が取れる。
逆に言うと、取れなかった場合は範囲外がクリックされたということになる。
テーブルのセルをクリックした時にそのセルを編集する例。
マウスのクリックイベントを拾ってセルのエディターを作成する。
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といった値もある)