by Lars Vogel

Follow me on twitter

Lars Vogel on Google+

Eclipse JFace Table - Tutorial

Lars Vogel, Clemens Muessener

Version 2.8

13.01.2012

Revision History
Revision 0.1 01.07.2007 Clemens Muessener, Lars Vogel
created
Revision 0.2 - 2.8 12.09.2007 - 13.01.2012 Lars
Vogel
bug fixes and enhancements

Eclipse JFace Table

This tutorial explains the usage of Eclipse JFace TableViewer including label and content provider.

This tutorial is based on Eclipse 3.7 (Indigo).


Table of Contents

1. JFace Table Viewer
1.1. Viewer
1.2. ContentProvider
1.3. Columns and LabelProviders
2. Prerequisites
3. Tutorial: JFace Table Viewer
3.1. Overview of the example
3.2. Project creation and data model
3.3. Define the viewer
3.4. Run
4. Advanced JFace Table
5. Thank you
6. Questions and Discussion
7. Download
8. Links and Literature
8.1. Source Code
8.2. JFace Resources
8.3. vogella Resources

1. JFace Table Viewer

1.1. Viewer

You can use the TableViewer class to create tables using the JFace framework.

This Viewer requires a ContentProvider which provides structured data to the Viewer, e.g. an Array or a list.

You also define LabelProviders per column, which define how the data in the column is displayed.

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

// Create the columns 
// Not yet implemented
createColumns(parent);

// Make lines and make header visible
final Table table = viewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);

			

1.2. ContentProvider

A ContentProvider delivers the data which should be displayed in the table.

You can implement your own ContentProvider for a table by implementing the interface org.eclipse.jface.viewers.IStructuredContentProvider.

Eclipse provides already an implementation of this interface via the ArrayContentProvider class. ArrayContentProvider supports Arrays or Lists as basis for the underlying data. As ArrayContentProvider does not store any data, you can share instances. To get a shared instance use the ArrayContentProvider.getInstance() method.

The getElements() method of the ContentProvider is called by the JFace table Viewer to translate the input into an array of elements.

These elements are displayed as individual elements by the table Viewer, i.e. as individual rows.

The input to the ContentProvider is provided via the setInput() method of the Viewer.

				
// Continued after the definition of 
// the Viewer

// Set the ContentProvider
viewer.setContentProvider(ArrayContentProvider.getInstance());

// Get the content for the Viewer,
// setInput will call getElements in the ContentProvider
viewer.setInput(someData...);
			

1.3. Columns and LabelProviders

Columns for a JFace table Viewer are defined via instances of TableViewerColumn.

Each TableViewerColumn needs to get a LabelProvider assigned via the setLabelProvider() method. The LabelProvider defines how the data from the model will be displayed. Typically you return the String which should be displayed.

The setLabelProvider() method expects an instance of the abstract CellLabelProvider class. A default implementation of this class is provided by the ColumnLabelProvider class.

				
// This will create the columns for the table
private void createColumns(final Composite parent, final TableViewer viewer) {
	String[] titles = { "First name", "Last name", "Married" };
	int[] bounds = { 100, 100, 100 };

	// First column is for the first name
	TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
	col.setLabelProvider(new ColumnLabelProvider() {
		@Override
		public String getText(Object element) {
			Person p = (Person) element;
			return p.getFirstName();
		}
	});

	// Second column is for the last name
	col = createTableViewerColumn(titles[1], bounds[1], 1);
	col.setLabelProvider(new ColumnLabelProvider() {
		@Override
		public String getText(Object element) {
			Person p = (Person) element;
			return p.getLastName();
		}
	});

	// Now the status married
	// Uses also an Image
	col = createTableViewerColumn(titles[2], bounds[2], 2);
	col.setLabelProvider(new ColumnLabelProvider() {
		@Override
		public String getText(Object element) {
		  return null;
		}

		@Override
		public Image getImage(Object element) {
		  if (((Person) element).isMarried()) {
			return CHECKED;
		  } 
		  return UNCHECKED;
		}
	});

}
			

You can also use StyledCellLabelProvider which extends CellLabelProvider. StyledCellLabelProvider provides the possibility to style the text, e.g with colors or icon decorators.

Before Eclipse 3.3 you had to use the ITableLabelProvider interface to define label providers. This interface is outdated and should not be used in new projects.

2. Prerequisites

The following provides an example how to build a table with the JFace Viewer framework.

It assume that you are familiar with creating Eclipse RCP applications or Eclipse Plug-ins .

Please see Introduction to JFace for an introduction to the concepts behind this example.

3. Tutorial: JFace Table Viewer

3.1. Overview of the example

We will build an Eclipse RCP application which displays data of persons in a JFace table. Each person is displayed in one individual row. This tutorial the basic setup of a JFace Table.

The final application will look like this.

3.2. Project creation and data model

Create a new RCP Project de.vogella.jface.tableviewer using the "RCP application with a view" as a template. Create a package "de.vogella.jface.tableviewer.model" and the following class "Person".

				
package de.vogella.jface.tableviewer.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Person {
	private String firstName;
	private String lastName;
	private boolean married;
	private String gender;
	private Integer age;
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	public Person() {
	}

	public Person(String firstName, String lastName, String gender,
			boolean married) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.gender = gender;
		this.married = married;
	}

	public void addPropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public String getFirstName() {
		return firstName;
	}

	public String getGender() {
		return gender;
	}

	public String getLastName() {
		return lastName;
	}

	public boolean isMarried() {
		return married;
	}

	public void setFirstName(String firstName) {
		propertyChangeSupport.firePropertyChange("firstName", this.firstName,
				this.firstName = firstName);
	}

	public void setGender(String gender) {
		propertyChangeSupport.firePropertyChange("gender", this.gender,
				this.gender = gender);
	}

	public void setLastName(String lastName) {
		propertyChangeSupport.firePropertyChange("lastName", this.lastName,
				this.lastName = lastName);
	}

	public void setMarried(boolean isMarried) {
		propertyChangeSupport.firePropertyChange("married", this.married,
				this.married = isMarried);
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		propertyChangeSupport.firePropertyChange("age", this.age,
				this.age = age);
	}

	@Override
	public String toString() {
		return firstName + " " + lastName;
	}

}
			

The class "Person" represents the data model for this example. It has also propertyChange support, which is not necessary for this example but is nice if you would later extend this example with Eclipse Databinding support.

Create the ModelProvider class which is a in-memory representation of your data. This class is defined as a Singleton.

				
package de.vogella.jface.tableviewer.model;

import java.util.ArrayList;
import java.util.List;

public enum ModelProvider {
	INSTANCE;

	private List<Person> persons;

	private ModelProvider() {
		persons = new ArrayList<Person>();
		// Image here some fancy database access to read the persons and to
		// put them into the model
		persons.add(new Person("Rainer", "Zufall", "male", true));
		persons.add(new Person("Reiner", "Babbel", "male", true));
		persons.add(new Person("Marie", "Dortmund", "female", false));
		persons.add(new Person("Holger", "Adams", "male", true));
		persons.add(new Person("Juliane", "Adams", "female", true));
	}

	public List<Person> getPersons() {
		return persons;
	}

}

			

3.3.  Define the viewer

Change the class "View.java" to the following.

				
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.model.Person;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;
	// We use icons
	private static final Image CHECKED = Activator.getImageDescriptor(
			"icons/checked.gif").createImage();
	private static final Image UNCHECKED = Activator.getImageDescriptor(
			"icons/unchecked.gif").createImage();

	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText("Search: ");
		final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));
		createViewer(parent);
	}

	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(parent, viewer);
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		viewer.setContentProvider(new ArrayContentProvider());
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.INSTANCE.getPersons());
		// Make the selection available to other views
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		// First column is for the first name
		TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Person p = (Person) element;
				return p.getFirstName();
			}
		});

		// Second column is for the last name
		col = createTableViewerColumn(titles[1], bounds[1], 1);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Person p = (Person) element;
				return p.getLastName();
			}
		});

		// Now the gender
		col = createTableViewerColumn(titles[2], bounds[2], 2);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Person p = (Person) element;
				return p.getGender();
			}
		});

		// // Now the status married
		col = createTableViewerColumn(titles[3], bounds[3], 3);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				return null;
			}

			@Override
			public Image getImage(Object element) {
				if (((Person) element).isMarried()) {
					return CHECKED;
				} else {
					return UNCHECKED;
				}
			}
		});

	}

	private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
				SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}

	
/** * Passing the focus request to the viewer's control. */
public void setFocus() { viewer.getControl().setFocus(); } }

The method createColumns create the table columns, headers, sets the size of the columns and makes the columns re-sizable.

createTableViewerColumn() has three parameters. The third is currently not used, but we will use it in the advanced tutorial .

Tip

Please note that we use icons for the married Status. If the folder "icons" does not exists in your project create it. Download the icons and place the two icons in the folder icons. Alternatively you can only use the setText() method.

3.4. Run

Run the example. The application should display a non-working search field and a table.

4. Advanced JFace Table

For more options on configuring your JFace Table please see Eclipse JFace Table Advanced Tutorial

This tutorial explains advanced usage of the JFace TableViewer including inline table editing, table filtering and sorting, and model / view interaction. StyledLabelProvider are also discussed.

5. Thank you

Please help me to support this article:

Flattr this

6. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.de Google Group. I have created a short list how to create good questions which might also help you.

7. Download

http://www.vogella.de/articles/EclipseJFaceTable/download/checkedpics.zip The checkbox pictures for the JFace Labelprovider

8. Links and Literature

8.1. Source Code

Source Code of Examples

8.2. JFace Resources

Eclipse JFace

JFace Tree Tutorial

JFace Data Binding

http://www.eclipse.org/articles/Article-Table-viewer/table_viewer.html Building and delivering a table editor with SWT/JFace

http://wiki.eclipse.org/index.php/JFaceSnippets JFace snippets, e.g. small code examples

8.3. vogella Resources

Eclipse RCP Training (German) Eclipse RCP Training with Lars Vogel

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java and compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put everything you have under distributed version control system