Eclipse JFace TreeViewer tutorial. This tutorial explains the usage of Eclipse JFace TreeViewer. It shows the usage of a DelegatingStyledCellLabelProvider.
1. Prerequisites
Please see Introduction to JFace for an introduction to the concepts behind this example.
For an example of how to build JFace tables, please see JFace Table Tutorial.
2. JFace TreeViewer
2.1. Using viewers to display a tree
The TreeViewer
class provides viewer support for displaying trees. The usage of this class is similar to the TableViewer
class.
The main difference is that the TreeViewer
class requires a structured content provider.
Typically, your content provider has to implement the ITreeContentProvider
interface to be used with your TreeViewer
class.
A TreeViewer can be used similar to a TableViewer, which just shows a list of elements by using the following content provider:
public class TreeContentProvider implements ITreeContentProvider {
@Override
public boolean hasChildren(Object element) {
return false;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public Object[] getElements(Object inputElement) {
return ArrayContentProvider.getInstance().getElements(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
return null;
}
}
This ITreeContentProvider
just delegates to the ArrayContentProvider
in its getElements
method and the elements have no children.
@PostConstruct
public void postConstruct(Composite parent) {
TreeViewer viewer = new TreeViewer(parent);
viewer.setContentProvider(new TreeContentProvider());
viewer.getTree().setHeaderVisible(true);
viewer.getTree().setLinesVisible(true);
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
viewerColumn.getColumn().setWidth(300);
viewerColumn.getColumn().setText("Names");
viewerColumn.setLabelProvider(new ColumnLabelProvider());
viewer.setInput(new String[] { "Simon Scholz", "Lars Vogel", "Dirk Fauth", "Wim Jongman", "Tom Schindl" });
GridLayoutFactory.fillDefaults().generateLayout(parent);
}
2.2. Selection and double-click listener
JFace allows you to access the SWT controls to define listeners on your viewer.
For example, you can add a SelectionListener
implementation to the SWT control which is wrapped in the JFace object.
The following code snippet demonstrates how to expand a tree with a mouse click.
// the viewer field is an already configured TreeViewer
Tree tree = (Tree) viewer.getControl();
tree.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem item = (TreeItem) e.item;
if (item.getItemCount() > 0) {
item.setExpanded(!item.getExpanded());
// update the viewer
viewer.refresh();
}
}
});
Viewers allow you to attach specific listeners directly.
The following example shows how to expand an instance of a TreeViewer
with a double-click.
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
TreeViewer viewer = (TreeViewer) event.getViewer();
IStructuredSelection thisSelection = (IStructuredSelection) event.getSelection();
Object selectedNode = thisSelection.getFirstElement();
viewer.setExpandedState(selectedNode,
!viewer.getExpandedState(selectedNode));
}
});
2.3. Adjusting tree columns when expanded
If a TreeViewer
has multiple columns, clipping the first column (containing expandable items) looks unprofessional.

To make a column fit its content, you can call the column’s pack()
method as follows:
// the viewer field is an already configured TreeViewer
Tree tree = (Tree) viewer.getControl();
Listener listener = new Listener() {
@Override
public void handleEvent(Event event) {
TreeItem treeItem = (TreeItem) event.item;
final TreeColumn[] treeColumns = treeItem.getParent().getColumns();
display.asyncExec(new Runnable() {
@Override
public void run() {
for (TreeColumn treeColumn : treeColumns)
treeColumn.pack();
}
});
}
};
tree.addListener(SWT.Expand, listener);
With this code every column of the Tree
will have the appropriate width, when a TreeItem
is expanded, so that the contents of the column is not clipped.
2.4. Increasing the font size
The font size can be increased by setting a Font for the underlying SWT Tree.
@PostConstruct
public void postConstruct(Composite parent) {
ResourceManager resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
TreeViewer viewer = new TreeViewer(parent);
viewer.setContentProvider(new TreeContentProvider());
viewer.getTree().setHeaderVisible(true);
viewer.getTree().setLinesVisible(true);
viewer.getTree().setFont(resourceManager.createFont(FontDescriptor.createFrom("Arial", 32, SWT.ITALIC)));
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
viewerColumn.getColumn().setWidth(300);
viewerColumn.getColumn().setText("Names");
viewerColumn.setLabelProvider(new ColumnLabelProvider());
viewer.setInput(new String[] { "Simon Scholz", "Lars Vogel", "Dirk Fauth", "Wim Jongman", "Tom Schindl" });
GridLayoutFactory.fillDefaults().generateLayout(parent);
}
3. Optional exercise: Implementing a File browser
Now you will create a file browser for your file system using a TreeViewer
.
This exercise is standalone and can be used to practice the steps for creating an Eclipse RCP application.
3.1. Create a new application
Use the
menu entry and create a new Eclipse RCP application named com.example.e4.filebrowser without sample data. Make sure to uncheck Create sample content on the last page of the wizard.
3.2. Update the manifest dependencies
Ensure that you have correct dependencies.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Filebrowser
Bundle-SymbolicName: com.example.e4.filebrowser;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: EXAMPLE
Require-Bundle: org.eclipse.jface,
org.eclipse.e4.ui.di,
org.eclipse.core.runtime
Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.example.e4.filebrowser
Import-Package: jakarta.annotation;version="[2.1.0,3.0.0)"
Require-Capability: eclipse.swt;filter:="(image.format=svg)"
3.3. Add an image file
If the new project does not have an icons folder, create one.
Download or create an icon named folder.svg. For example, https://fonts.google.com/icons allows to download SVG or PNG files for a folder. Place this image into a new folder named icons in the com.example.e4.filebrowser plug-in.
3.4. Create the view implementation
Use Ctrl+Shift+T to open the ITreeContentProvider
interface.
Review the Javadoc of this class to understand the methods of this interface.
Afterwards, implement the following class.
It assumes that you added the folder.svg icon to the icons folder.
It demonstrates the usage of a ViewLabelProvider
.
package com.example.e4.filebrowser;
import java.io.File;
import java.net.URL;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import jakarta.annotation.PostConstruct;
public class FileBrowserPart {
private TreeViewer viewer;
@PostConstruct
public void createControls(Composite parent) {
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
new ViewLabelProvider(createImageDescriptor())));
viewer.setInput(File.listRoots());
}
private ImageDescriptor createImageDescriptor() {
Bundle bundle = FrameworkUtil.getBundle(ViewLabelProvider.class);
URL url = FileLocator.find(bundle, new Path("icons/folder.svg"), null);
return ImageDescriptor.createFromURL(url);
}
class ViewContentProvider implements ITreeContentProvider {
@Override
public Object[] getElements(Object inputElement) {
return (File[]) inputElement;
}
@Override
public Object[] getChildren(Object parentElement) {
File file = (File) parentElement;
return file.listFiles();
}
@Override
public Object getParent(Object element) {
File file = (File) element;
return file.getParentFile();
}
@Override
public boolean hasChildren(Object element) {
File file = (File) element;
if (file.isDirectory()) {
return true;
}
return false;
}
}
class ViewLabelProvider extends LabelProvider implements IStyledLabelProvider {
private ImageDescriptor directoryImage;
private ResourceManager resourceManager;
public ViewLabelProvider(ImageDescriptor directoryImage) {
this.directoryImage = directoryImage;
}
@Override
public StyledString getStyledText(Object element) {
if(element instanceof File) {
File file = (File) element;
StyledString styledString = new StyledString(getFileName(file));
String[] files = file.list();
if (files != null) {
styledString.append(" ( " + files.length + " ) ",
StyledString.COUNTER_STYLER);
}
return styledString;
}
return null;
}
@Override
public Image getImage(Object element) {
if(element instanceof File) {
if(((File) element).isDirectory()) {
return getResourceManager().create(directoryImage);
}
}
return super.getImage(element);
}
@Override
public void dispose() {
// garbage collect system resources
if(resourceManager != null) {
resourceManager.dispose();
resourceManager = null;
}
}
protected ResourceManager getResourceManager() {
if(resourceManager == null) {
resourceManager = new LocalResourceManager(JFaceResources.getResources());
}
return resourceManager;
}
private String getFileName(File file) {
String name = file.getName();
return name.isEmpty() ? file.getPath() : name;
}
}
@Focus
public void setFocus() {
viewer.getControl().setFocus();
}
}
3.5. Update the application model
The application window should be named File Browser.

Create a new model for the part. Link from your part in the application model to your new class. We do not need a stack, therefore directly add a part stack with a part to your application model.

3.6. Validate
Start your new application ensure that you see the content of your file system in your tree.

4. Optional exercise: Add multiple columns to a tree viewer
This exercise extends the work from the Optional exercise: Implementing a File browser exercise. |
4.1. Using TreeViewerColumns in the file browser
To add multiple columns to a TreeViewer
, the TreeViewerColumn
class is used.
A TreeViewerColumn
itself is a wrapper around the TreeColumn
widget from SWT.
// make the table header visible to see the column's text
viewer.getTree().setHeaderVisible(true);
TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn column = viewerColumn.getColumn();
column.setText("Name");
column.setWidth(300);
Instead of applying a single CellLabelProvider
to the entire viewer, each TreeViewerColumn
can have its own CellLabelProvider
.
This allows you to define the label for each column separately.
To do so, assign a label provider to the column using the TreeViewerColumn#setLabelProvider
method.
package com.example.e4.filebrowser;
import java.io.File;
import java.net.URL;
import java.text.DateFormat;
import java.util.Date;
import jakarta.annotation.PostConstruct;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
public class FileBrowserPart {
private TreeViewer viewer;
private static final DateFormat dateFormat = DateFormat.getDateInstance();
@PostConstruct
public void createControls(Composite parent) {
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.getTree().setHeaderVisible(true);
TreeViewerColumn mainColumn = new TreeViewerColumn(viewer, SWT.NONE);
mainColumn.getColumn().setText("Name");
mainColumn.getColumn().setWidth(300);
mainColumn.setLabelProvider(
new DelegatingStyledCellLabelProvider(
new ViewLabelProvider(createImageDescriptor())));
TreeViewerColumn modifiedColumn = new TreeViewerColumn(viewer, SWT.NONE);
modifiedColumn.getColumn().setText("Last Modified");
modifiedColumn.getColumn().setWidth(100);
modifiedColumn.getColumn().setAlignment(SWT.RIGHT);
modifiedColumn
.setLabelProvider(new DelegatingStyledCellLabelProvider(
new FileModifiedLabelProvider(dateFormat)));
TreeViewerColumn fileSizeColumn = new TreeViewerColumn(viewer, SWT.NONE);
fileSizeColumn.getColumn().setText("Size");
fileSizeColumn.getColumn().setWidth(100);
fileSizeColumn.getColumn().setAlignment(SWT.RIGHT);
fileSizeColumn.setLabelProvider(new DelegatingStyledCellLabelProvider(
new FileSizeLabelProvider()));
viewer.setInput(File.listRoots());
}
private ImageDescriptor createImageDescriptor() {
Bundle bundle = FrameworkUtil.getBundle(ViewLabelProvider.class);
URL url = FileLocator.find(bundle, new Path("icons/folder.svg"), null);
return ImageDescriptor.createFromURL(url);
}
class ViewContentProvider implements ITreeContentProvider {
@Override
public Object[] getElements(Object inputElement) {
return (File[]) inputElement;
}
@Override
public Object[] getChildren(Object parentElement) {
File file = (File) parentElement;
return file.listFiles();
}
@Override
public Object getParent(Object element) {
File file = (File) element;
return file.getParentFile();
}
@Override
public boolean hasChildren(Object element) {
File file = (File) element;
if (file.isDirectory()) {
return true;
}
return false;
}
}
class ViewLabelProvider extends LabelProvider implements IStyledLabelProvider {
private ImageDescriptor directoryImage;
private ResourceManager resourceManager;
public ViewLabelProvider(ImageDescriptor directoryImage) {
this.directoryImage = directoryImage;
}
@Override
public StyledString getStyledText(Object element) {
if (element instanceof File) {
File file = (File) element;
StyledString styledString = new StyledString(getFileName(file));
String[] files = file.list();
if (files != null) {
styledString.append(" ( " + files.length + " ) ", StyledString.COUNTER_STYLER);
}
return styledString;
}
return null;
}
@Override
public Image getImage(Object element) {
if (element instanceof File) {
if (((File) element).isDirectory()) {
return getResourceManager().create(directoryImage);
}
}
return super.getImage(element);
}
@Override
public void dispose() {
// garbage collection system resources
if (resourceManager != null) {
resourceManager.dispose();
resourceManager = null;
}
}
protected ResourceManager getResourceManager() {
if (resourceManager == null) {
resourceManager = new LocalResourceManager(JFaceResources.getResources());
}
return resourceManager;
}
private String getFileName(File file) {
String name = file.getName();
return name.isEmpty() ? file.getPath() : name;
}
}
class FileModifiedLabelProvider extends LabelProvider implements IStyledLabelProvider {
private DateFormat dateLabelFormat;
public FileModifiedLabelProvider(DateFormat dateFormat) {
dateLabelFormat = dateFormat;
}
@Override
public StyledString getStyledText(Object element) {
if (element instanceof File) {
File file = (File) element;
long lastModified = file.lastModified();
return new StyledString(dateLabelFormat.format(new Date(lastModified)));
}
return null;
}
}
class FileSizeLabelProvider extends LabelProvider implements IStyledLabelProvider {
@Override
public StyledString getStyledText(Object element) {
if (element instanceof File) {
File file = (File) element;
if (file.isDirectory()) {
// a directory is just a container and has no size
return new StyledString("0");
}
return new StyledString(String.valueOf(file.length()));
}
return null;
}
}
@Focus
public void setFocus() {
viewer.getControl().setFocus();
}
}
4.2. Validate
Start your new application and verify that you see the content of your file system in your tree.

5. Searchable TreeViewer
This example shows how to make a JFace TreeViewer searchable. Pressing Ctrl-F opens a search dialog. If a tree item is found it gets selected.
public class SearchDialog extends Dialog {
public SearchDialog(Shell parent) {
super(parent);
}
private Tree tree;
private SearchableTreeViewer searchableTreeViewer;
private Button searchButton;
private Text searchField;
private TreeSearchAlgorithm algorithm;
public SearchDialog(Shell parent, SearchableTreeViewer searchableTreeViewer, TreeSearchAlgorithm algorithm) {
super(parent);
this.searchableTreeViewer = searchableTreeViewer;
this.algorithm = algorithm;
tree = searchableTreeViewer.getTree();
}
@Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
container.setLayout(new FillLayout());
searchField = new Text(container, SWT.NONE);
return container;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
searchButton = createButton(parent, IDialogConstants.PROCEED_ID, "Search", false);
searchButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(this::search));
}
private void search(SelectionEvent event) {
TreeItem found = algorithm.search(tree.getItems(), searchField.getText());
if (found != null) {
searchableTreeViewer.setSelection(new StructuredSelection(found.getData()), true);
close();
} else {
System.out.println("Nothing Found");
}
}
}
public interface TreeSearchAlgorithm {
public TreeItem search(TreeItem[] treeItems, String searchTerm);
}
public class TreeContentProvider implements ITreeContentProvider {
@Override
public boolean hasChildren(Object element) {
return false;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public Object[] getElements(Object inputElement) {
return ArrayContentProvider.getInstance().getElements(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
return null;
}
}
public class SearchableTreeViewer extends TreeViewer {
private Composite parent;
public SearchableTreeViewer(Composite parent, TreeSearchAlgorithm algorithm) {
super(parent);
this.parent = parent;
parent.addKeyListener(KeyListener.keyPressedAdapter(event -> {
if (event.stateMask == SWT.CTRL && event.keyCode == 'f') {
startSearchDialog(algorithm);
}
}));
}
private void startSearchDialog(TreeSearchAlgorithm algorithm) {
SearchDialog searchDialog = new SearchDialog(parent.getShell(), this, algorithm);
searchDialog.open();
}
}
public class TreeWindow extends ApplicationWindow {
public TreeWindow() {
super(null);
// Don't return from open() until window closes
setBlockOnOpen(true);
// Open the main window
open();
// Dispose the display
Display.getCurrent().dispose();
}
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
// Set the title bar text and the size
shell.setText("Searchable Tree");
shell.setSize(400, 400);
}
@Override
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new FillLayout());
SearchableTreeViewer treeViewer = new SearchableTreeViewer(composite,
(treeItems, searchText) -> {
for (TreeItem item : treeItems) {
if (item.getText().toUpperCase().contains(searchText.toUpperCase())) {
return item;
};
}
return null;
});
treeViewer.setContentProvider(new TreeContentProvider());
TreeViewerColumn viewerColumn = new TreeViewerColumn(treeViewer, SWT.NONE);
treeViewer.getTree().setHeaderVisible(true);
treeViewer.getTree().setLinesVisible(true);
viewerColumn.getColumn().setWidth(300);
viewerColumn.getColumn().setText("Names");
viewerColumn.setLabelProvider(new ColumnLabelProvider());
treeViewer.setInput(new String[] { "Simon Scholz", "Lars Vogel", "Dirk Fauth", "Wim Jongman", "Tom Schindl" });
return composite;
}
public static void main(String[] args) {
new TreeWindow();
}
}
6. Learn more and get support
This tutorial continues on Eclipse RCP online training or Eclipse IDE extensions with lots of video material, additional exercises and much more content.
7. Links and Literature
7.2. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting