JFace TableViewer
Ein JFace TableViewer funktioniert ähnlich zum Combo-/ListViewer. Hinzu kommt hier lediglich, dass je ein LabelProvider für jede Spalte gesetzt wird. Dazu ist zunächst für jede Spalte ein JFace TableViewerColumn-Objekt anzulegen. Dieses erzeugt und verwaltet eine SWT TableColumn:
TableViewerColumn viewerNameColumn = new TableViewerColumn(tableViewer, SWT.NONE);
viewerNameColumn.getColumn().setText("Some Column");
viewerNameColumn.getColumn().setWidth(100);
Den Spalten ist ein LabelProvider zu setzen. Der LabelProvider ist dafür zuständig, die Zellen der Spalte zu befüllen. Je Tabellenzelle wird er einmal aufgerufen, um die Zelle mit Inhalten zu befüllen. Dabei hat er das Element für die jeweilige Zeile zur Verfügung:
TableViewerColumn viewerNameColumn = new TableViewerColumn(tableViewer, SWT.NONE);
viewerNameColumn.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
cell.setText(((SomeObject) cell.getElement()).getSomeProperty());
}
});
Zusammengefasst: Ein TableViewer befüllt eine SWT Table mit Inhalten aus seinem Input-Objekt. Der ContentProvider konvertiert dazu das Input-Objekt in Zeilenobjekte. Jede Spalte des TableViewers bekommt einen CellLabelProvider gesetzt, der die Zellen der Spalte mit den Daten aus dem Zeilenobjekt befüllt:
// JFace TableViewer
TableViewer tableViewer = new TableViewer(parentComposite, SWT.NONE);
// SWT Table
Table table = tableViewer.getTable();
// Spaltenköpfe und Zeilenbegrenzungen sichtbar machen
table.setHeaderVisible(true);
table.setLinesVisible(true);
// ArrayContentProvider kann verwendet werden, da Input-Objekt eine Java Collection ist
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
// Für jede Spalte ein TableViewerColumn erzeugen
TableViewerColumn viewerNameColumn = new TableViewerColumn(tableViewer, SWT.NONE);
viewerNameColumn.getColumn().setText("Test");
viewerNameColumn.getColumn().setWidth(100);
// LabelProvider für jede Spalte setzen
viewerNameColumn.setLabelProvider(new CellLabelProvider() {
public void update(ViewerCell cell) {
cell.setText(((SomeObject) cell.getElement()).getSomeProperty());
}
});
// List<SomeObject> als Input-Objekt setzen
tableViewer.setInput(someList);
Prozentuale Spaltenbreiten
Mit TableColumnLayout kann die Breite von Tabellenspalten prozentual verteilt werden. Dazu wird ein Composite um die Tabelle herum benötigt, welches nur die Tabelle enthält. Diesem wird das TableColumnLayout gesetzt. Das Layout übernimmt dann die Verteilung der Spaltenbreiten in der enthaltenen Tabelle:
Composite tableComposite = new Composite(parent, SWT.NONE);
TableColumnLayout tableColumnLayout = new TableColumnLayout();
tableComposite.setLayout(tableColumnLayout);
TableViewer tableViewer = new TableViewer(tableComposite, SWT.BORDER | SWT.FULL_SELECTION);
Auf dem Layout-Objekt kann für jede Spalte ein ColumnLayoutData-Objekt gesetzt werden, um dem Layout den Platzbedarf der Tabellenspalte mitzuteilen:
tableColumnLayout.setColumnData(viewerNameColumn.getColumn(), new ColumnPixelData(50));
ColumnPixelData erlaubt die absolute Angabe einer Spaltenbreite in Pixeln, ColumnWeightData erlaubt die Angabe einer prozentualen Spaltengewichtung, minimaler Breite in Pixel sowie die Angabe, ob die Spaltenbreite vom Benutzer verändert werden darf:
public ColumnPixelData(int width)
public ColumnWeightData(int weight, int minimumWidth, boolean resizable)
Tabellen sortieren
Um die Reihenfolge der Zeilen eines JFace TableViewers festzulegen, kann dem TableViewer ein ViewerComparator gesetzt werden:
tableViewer.setComparator(ViewerComparator comparator)
Die Sortierung erfolgt dabei rein auf Anzeigeebene, das zugrundeliegende Input-Objekt bleibt unverändert. Der ViewerComparator implementiert die Vergleichsoperation für die Zeilen-Elemente und legt so die Reihenfolge der Zeilen fest:
tableViewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof SomeObject && e2 instanceof SomeObject) {
return ((SomeObject) e1).getName().compareToIgnoreCase(
((SomeObject) e2).getName());
}
throw new IllegalArgumentException("Not comparable: " + e1 + " " + e2);
}
});
Tabellen filtern
Um die Zeilen eines JFace StructuredViewers zu filtern, kann mit addFilter bzw. setFilters eine Liste von ViewerFilter-Objekten gesetzt werden. Die jeweilige Zeile wird nur dann zur Anzeige gebracht, wenn alle gesetzten Filter der Anzeige zugestimmt haben. So lässt sich beispielsweise eine Suche über die Inhalte der Tabelle realisieren:
ViewerFilter searchFilter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
return ((SomeObject) element).getName().contains("searchString");
}
};
tableViewer.addFilter(searchFilter);
Editierbare Tabellen
Die Spalten in einem JFace-Viewer können editierbar gemacht werden, indem auf der TableViewerColumn ein EditingSupport-Objekt für die Spalte gesetzt wird. Durch die EditingSupport-Implementierung wird festgelegt, welche Zellen bearbeitbar sein sollen, welches Control zur Bearbeitung verwendet werden soll (im Beispiel TextCellEditor) und wie die Werte zu holen und zu setzen sind:
tableViewerColumn.setEditingSupport(new EditingSupport(tableViewer) {
protected boolean canEdit(Object element) {
return true;
}
protected CellEditor getCellEditor(Object element) {
return new TextCellEditor(tableViewer.getTable());
}
protected Object getValue(Object element) {
return ((SomeObject) element).getName();
}
protected void setValue(Object element, Object value) {
((SomeObject) element).setName(String.valueOf(value));
tableViewer.refresh(element);
}
});
Als CellEditor stehen TextCellEditor, ColorCellEditor, ComboBoxCellEditor, CheckboxCellEditor sowie DialogCellEditor zur Verfügung.



Sehr übersichtliches und schönes Tutorial. Es fehlen jedoch noch die Sort-Indikatoren auf Tabellenspalten(irgendwie so):
for (int i = 0; i < 3; i++) {
final TableViewerColumn column = new TableViewerColumn(table, SWT.NONE);
column.getColumn().addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
table.getTable().setSortColumn(column.getColumn());
int direction = (table.getTable().getSortDirection()&SWT.UP)==SWT.UP?SWT.DOWN:SWT.UP;
table.getTable().setSortDirection();
}
});
}
Viele Grüsse
Wolfgang Geck