Version 2.5
Copyright © 2010, 2011, 2012 Lars Vogel
22.08.2012
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 21.05.2010 | Lars Vogel |
Started |
| Revision 0.2 - 2.5 | 24.05.2010 - 22.08.2012 | Lars Vogel |
Bugfixes and Enhancements |
Table of Contents
The Standard Widget Toolkit (SWT) is the user interface library used by Eclipse. It provides widgets, e.g. buttons and text fields, as well as layout managers. Layout managers are used to arrange the widgets according to a certain rule set.
SWT supports several platforms, e.g. Windows, Linux and Mac OS X. The design target of SWT is to stay closely to the operating system (OS); therefore the SWT API (Application Programming Interface) is very close to the native API of the OS.
As the SWT API is relatively low-level, programmers typically also use JFace.
SWT uses the native widgets of the platform whenever possible. The native widgets of the OS are accessed by the SWT framework via the Java Native Interface framework. The Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call, and to be called by, native applications and libraries written in other languages such as C, C++ and assembler.
The approach of using native widgets can also be found in
AWT, a
standard user interface library available in Java.
In comparison
SWT
provides more widgets than
AWT, as
AWT
does not provide
widgets
if
they are not natively
available on all
platforms.
In case a widget is not available on one platform but on
another, SWT will emulate this widget on the first and uses the
native
widget on the latter. For
example
AWT
does not have table or tree widgets included, while
SWT
has.
The
Display
and
Shell
classes are key components of
SWT
applications.
A
org.eclipse.swt.widgets.Shell
class
represents a window.
The
org.eclipse.swt.widgets.Display
class is
responsible for
managing
event loops, for
controlling the
communication between the UI thread
and
other
threads and for
managing
fonts and colors.
Display
is the
base for
all
SWT
capabilities.
Every
SWT
application requires at
least one
Display
and one
or more
Shell
instances. The main
Shell
gets,
as a default parameter, a
Display
as a
constructor argument. Each
Shell
should be constructed with a
Display
as an input parameter.
An event loop is needed to communicate user input events from the underlying native operating system widgets to the SWT event system.
SWT
does not provide its own event loop. This means that the programmer
has to
explicitly start and check the event loop to update the user
interface. The loop will execute the
readAndDispatch()
method which reads events from the native widgets and
dispatches them
to the SWT event system. The loop is executed until the
main shell is
closed. If this loop was left out, the application would
terminate
immediately.
For example the following creates an SWT application and creates and executes the event loop.
Display display = new Display(); Shell shell = new Shell(display); shell.open(); // Create and check the event loop while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose();
If SWT is used in an Eclipse Plug-in or an Eclipse RCP application, this event loop is provided by the Eclipse framework.
Eclipse applications typically use SWT for the user interface. But it is possible to use other user interface toolkits, e.g. JavaFX, as Eclipse 4 provides a flexible Rendering Framework which allows you to specify the classes responsible for rendering.
If you develop Eclipse Plug-ins which extend the Eclipse IDE itself you have to use SWT as the Eclipse IDE Workbench uses an SWT renderer.
The Eclipse IDE ships with the SWT library and you can use this library in your project. The SWT library is packaged as an Eclipse component, i.e. plug-in.
Eclipse provides
plug-in projects, which allows you to define
dependencies to
other plug-ins.
Eclipse uses itself (or more specifically
the
Target
Platform defined
in the Eclipse Preference) to make the
plug-ins available to your project based on
your dependency
definition. Eclipse automatically adds
the corresponding
jar
file to your project class
path.
This is a simple way of developing your SWT stand-alone application. If you export this application you need to add the SWT library to your export.
Dependencies for plug-ins are defined in the
MANIFEST.MF
file
which is located in the
META-INF
folder. Eclipse provides a default
editor for this file. You can add
dependencies on the
Dependencies
tab of this editor.
Create an Eclipse plug-in and define a dependency
to
org.eclipse.swt
in the
MANIFEST.MF
file.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: My SWT-based Plug-in Bundle-SymbolicName: de.vogella.swt Bundle-Version: 1.0.0.qualifier Require-Bundle: org.eclipse.swt Bundle-RequiredExecutionEnvironment: JavaSE-1.6
It is possible to use SWT for stand-alone applications.
To use SWT in stand-alone applications, you need to have the SWT library available. There are several ways of doing this. You can either download the SWT library or create an Eclipse plug-in project and define a dependency in this project.
Download the SWT library from the following URL:
http://www.eclipse.org/swt/
This ZIP file contains a
swt.jar
file which you need to add to the
classpath
of your SWT
project.
SWT
widgets are located in the packages
org.eclipse.swt.widgets
and
org.eclipse.swt.custom. Widgets extend either the
Widget
or the
Control
class.
While
SWT
tries to use native widgets as much as possible it is
not possible
to
fulfill all common requirements with the native widgets.
Therefore
some
widgets extend the capabilities
of the native platform. These are
part of
the
org.eclipse.swt.custom
package
and usually start with the additional prefix
C
to
indicate that they
are custom
widgets, e.g.
CCombo.
Compared to the
Combo
class, the
CCombo
class
provides
the ability to set the height of the widget.
Another
example is
StyledText, a class which provides
advanced features for displaying
text, e.g.
like drawing a background.
Widgets from the package
org.eclipse.swt.custom
are
implemented in pure Java while widgets from
org.eclipse.swt.widgets
use native code. Custom widgets are not supposed to use
the
internal
classes of
SWT
as these classes may be different on
different
platforms. Every custom
widget must extend the
Composite
or
Canvas
class.
API compliance is
guaranteed only for these base classes.
If the new
custom
widget is supposed to contain other widgets, it
should extend
Composite.
Otherwise it should extend the
Canvas
class.
SWT widgets are not automatically garbage collected. If you release
an
SWT
widget, you have to call its
dispose()
method. Fortunately a container, e.g. a
Shell
will call the
dispose()
method for all its children.
The automatic release does not work for Color, Cursor, Display, Font, GC, Image, Printer, Region, Widget and subclasses. These SWT objects need to be manually disposed.
SWT
widgets, except
Shell,
are always constructed with a parent widget which
contains them. This
is similar to AWT and different to Swing, where the
add()
method is used.
In the constructor of the widget stylebits are passed to the widget as a second parameter. Depending on the provided stylebits the widget adjusts its look and feel as well as its behavior. Each widget documents its supported stylebits in its Javadoc.
The possible stylebits are predefined in the
SWT
class.
If no
special style is required you can pass
SWT.NONE.
For example the following creates a push button.
new Button(shell, SWT.PUSH);
And the following creates a checkbox button.
new Button(shell, SWT.CHECK);
You can register listeners for specific events on SWT controls, e.g.
a
ModifyListener
to listen to changes in a
Text
widget
or a
SelectionLister
for selection
(click) events on a
Button
widget.
// define PUSH Button // for a checkbox button use SWT.CHECK stylebit Button button = new Button(shell, SWT.PUSH); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // Handle the selection event System.out.println("Called!"); } });
ModifyListener,
FocusListener
and
SelectionListener
are examples for these listener interfaces.
Eclipse usually provides empty default implementations for these interfaces. These follow the naming convention: → .
For
example
SelectionListener
has
the abstract class
SelectionAdapter
which pre-implements the methods of
SelectionListener. This allows you to use
SelectionAdapter
as base for an anonymous class where
only one of the two declared
methods
are needed.
If you want to add a listener to the whole application you can use the
Display
class. For example to add a global mouse listener use
addFilter(SWT.MouseMove, listener).
Create a new plug-in project called
com.examle.swt.widgets
via
→ → → → .
Enter the data in the wizard similar to the screenshot below. Make sure you de-select the This plug-in will make contributions to the UI and Generate an activator, a Java class that controls the plug-in's life cycle checkboxes.


Press the button on the second page of the wizard.
Open the
MANIFEST.MF
file
in the
META-INF
folder
and select the
Dependencies
tab.
Press the
button in the
Required Plug-ins
part and enter
org.eclipse.swt
as dependency.

Continue to use the
com.examle.swt.widgets
project.
Create the following class for a simple SWT application.
package com.example.swt.widgets; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class FirstSWTApplication { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); // Layout manager handle the layout // of the widgets in the container shell.setLayout(new FillLayout()); //TODO add some widgets to the Shell shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
To start your application, right-click on your Java class, and select
→ .
You will receive an empty window (Shell).
Change the TODO in the code to the following. Make sure you use
org.eclipse.swt
and not
java.awt
when adding the missing imports.
// Shell can be used as container Label label = new Label(shell, SWT.BORDER); label.setText("This is a label:"); label.setToolTipText("This is the tooltip of this label"); Text text = new Text(shell, SWT.NONE); text.setText("This is the text in the text widget"); text.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); text.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); // set widgets size to their preferred size text.pack(); label.pack();
If you now start the application you will get a
Shell
with two
Widgets
included.

Add
a
Label
and a
Text
widget to your application.
// Shell can be used as container Label label = new Label(shell, SWT.BORDER); label.setText("This is a label:"); label.setToolTipText("This is the tooltip of this label"); Text text = new Text(shell, SWT.NONE); text.setText("This is the text in the text widget"); text.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); text.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); // set widgets size to their preferred size text.pack(); label.pack();
If you now start the application you will get a small
Shell
with two
Widgets
included.

Add a
Button
widget to your application
and assign a
SelectionListener
to it. If the button is pressed, write "Called!" to the console.
// define PUSH Button // for a checkbox button use SWT.CHECK stylebit Button button = new Button(shell, SWT.PUSH); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // Handle the selection event System.out.println("Called!"); } });
A layout manager is
responsible for arranging the user interface
components
of a
container, e.g. a
Composite
on
the
screen.
SWT
offers several standard layout managers.
Table 1. Layout Manager
| Layout Manager | Description |
|---|---|
| AbsoluteLayout | Allows you to define the exact position and width and height of components. As user interfaces may be used on screens with different sizes this layout manager should be avoided. |
| FillLayout | Layouts equal-sized widgets in a single row or column. |
| RowLayout | Layouts widgets in a row or in a column, with fill, wrap, and spacing options. |
| GridLayout | Layouts widgets in a grid. |
| FormLayout | Layouts widgets by creating attachments for each of the sides of its container. |
Each
SWT
widget can get layout specific settings assigned to it via a specific
class, e.g.
GridData
for a
GridLayout.
For example you can
specify that a certain widget should take
two
columns in a
GridLayout
via the following coding.
button = new Button(parent, SWT.NONE); GridData gridData = new GridData(); gridData.horizontalSpan = 2; button.setLayoutData(gridData);
Please note that the
LayoutData
must match that used by the
layout manager,
otherwise the runtime will
throw
an exception.
The layout will be automatically calculated when the container is
displayed. You can tell a
Composite
to recalculate the layout with the
composite.layout()
method.
FillLayout
divides the available space provided by the container equally to all
widgets and can be set to
arrange the widgets either
horizontally(SWT.HORIZONTAL)
or vertically (SWT.VERTICAL). It also allows you to set the space between the widgets (attribute
spacing) and the margins of the widgets to the container via the
marginWidth
and
marginHeight
attributes.
RowLayout
orders UI components in a row (SWT.HORIZONTAL) or in a
column (SWT.VERTICAL).
RowLayout
supports wrapping of
fields (field
wrap) by default. You can define if widgets should have their
preferred
size
(default)
or if they should grab the available space
via the field
pack. You can also set margins at the top, bottom,
left and right. If you
set justify, the widgets will be spread through
the available space.
Each element can define its height and width via a
RowData
element.
GridLayout
allows you to arrange the user interface components in a Grid with a
certain number of columns, with the
option to define column and row
spanning.
GridData
objects should not be re-used as the
GridLayout
class
expects that every user interface
element has a unique
GridData
object.
You can use
new GridData()
and assign properties to the new object. Alternatively you can use
one of its richer constructors to define certain attributes during
construction. For example via the following constructor.
new GridData(horizontalAlignment,
verticalAlignment,
grabExcessHorizontalSpace,
grabExcessVerticalSpace,
horizontalSpan,
verticalSpan)
The most important attributes are defined as following:
Table 2. GridData
| Parameter | Description |
|---|---|
| horizontalAlignment |
how the control will be positioned horizontally
within a
cell,
one
of:
SWT.LEFT,
SWT.CENTER,
SWT.RIGHT, or
SWT.FILL
|
| verticalAlignment |
how the control will
be positioned vertically within a
cell,
one
of:
SWT.TOP,
SWT.CENTER,
SWT.END
(same as
SWT.BOTTOM), or
SWT.FILL
|
| grabExcessHorizontalSpace | whether the cell will be made wide enough to take all the remaining horizontal space |
| grabExcessVerticalSpace | whether cell will grab any remaining vertical space |
| horizontalSpan | the number of column cells that the control will take up |
| verticalSpan | the number of row cells that the control will take up |
| heightHint | heightHint specifies the preferred height in pixels |
| widthHint | widthHint specifies the preferred width in pixels |
If the widget has the
grabExcessHorizontalSpace
attribute set to true, it will grab available space in its container.
SWT.FILL
tells the widget to fill the available space.
grabExcessHorizontalSpace
and
SWT.FILL
are often used together.
The following shows an example for the usage of the
GridLayout
class in the
com.example.swt.widgets
project.
package de.vogella.swt.layouts; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; public class GridLayoutSWT { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); // Create a new Gridlayout with 2 columns // where the 2 column do not have the // same size GridLayout layout = new GridLayout(2, false); // set the layout of the shell shell.setLayout(layout); // Create a label and a button Label label = new Label(shell, SWT.NONE); label.setText("A label"); Button button = new Button(shell, SWT.PUSH); button.setText("Press Me"); // Create a new label that will spam two columns label = new Label(shell, SWT.BORDER); label.setText("This is a label"); // Create new layout data GridData data = new GridData(SWT.FILL, SWT.LEFT, true, false, 2, 1); label.setLayoutData(data); // Create a new label which is used as a separator label = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL); // Create new layout data data = new GridData(SWT.FILL, SWT.LEFT, true, false, 2, 1); data.horizontalSpan=2; label.setLayoutData(data); // Create a right aligned button Button b = new Button(shell, SWT.PUSH); b.setText("New Button"); data = new GridData(SWT.BOTTOM, SWT.LEFT, false, false, 2, 1); b.setLayoutData(data); Spinner spinner = new Spinner(shell, SWT.READ_ONLY); spinner.setMinimum(0); spinner.setMaximum(1000); spinner.setSelection(500); spinner.setIncrement(1); spinner.setPageIncrement(100); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); gridData.widthHint = SWT.DEFAULT; gridData.heightHint = SWT.DEFAULT; gridData.horizontalSpan=2; spinner.setLayoutData(gridData); Composite composite = new Composite(shell, SWT.BORDER); gridData = new GridData(SWT.FILL, SWT.FILL, true, false); gridData.horizontalSpan= 2; composite.setLayoutData(gridData); composite.setLayout(new GridLayout(1, false)); Text text = new Text(composite, SWT.NONE); text.setText("Testing"); gridData = new GridData(SWT.FILL, SWT.FILL, true, false); text.setLayoutData(gridData); text = new Text(composite, SWT.NONE); text.setText("Another test"); // gridData = new GridData(SWT.FILL, SWT.FILL, true, false); // text.setLayoutData(gridData); Group group = new Group(shell, SWT.NONE); group.setText("This is my group"); gridData = new GridData(SWT.FILL, SWT.FILL, true, false); gridData.horizontalSpan= 2; group.setLayoutData(gridData); group.setLayout(new RowLayout(SWT.VERTICAL)); text = new Text(group, SWT.NONE); text.setText("Another test"); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
If you start your application, it should look like the following screenshot.

Resize the window and see how the arrangement of the widgets change.
You can specify the tab order of controls via the
setTabList()
method of a
Composite.
package de.vogella.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class TabExample { public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display); shell.setLayout(new RowLayout()); Button b1 = new Button(shell, SWT.PUSH); b1.setText("Button1"); Button b2 = new Button(shell, SWT.PUSH); b2.setText("Button2"); Button b3 = new Button(shell, SWT.PUSH); b3.setText("Button3"); Control[] controls = new Control[] { b2, b1, b3 }; shell.setTabList(controls); shell.pack(); shell.open(); while (!display.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
The SWT Snippets give examples for stand-alone SWT applications using different kinds of SWT widgets. The SWT Snippet site is located at the following URL: http://www.eclipse.org/swt/snippets/.
You can copy these snippets and paste them directly into Eclipse on a Java package. Eclipse will automatically create the Java class for you.
If you do this on a project which has SWT already available, the snippet can be started immediately.
The SWT Examples page provides useful programs that are written in SWT. These are typically much larger and more comprehensive than SWT Snippets.The SWT Examples are located at the following URL: http://www.eclipse.org/swt/examples.php
In addition the Eclipse Nebula project provides additional widgets for SWT. The homepage can be found at the URL: http://eclipse.org/nebula/
Another source for SWT widgets is the Opal widget homepage: http://code.google.com/a/eclipselabs.org/p/opal/
SWT provides
DateTime
widgets. Create the following class.
package de.vogella.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DateTime; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class DateTimeExample { public static void main(String[] args) { // setup the SWT window Display display = new Display(); final Shell shell = new Shell(display); shell.setLayout(new RowLayout()); // initialize a parent composite with a grid layout manager Composite parent = new Composite(shell, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; parent.setLayout(gridLayout); DateTime calender = new DateTime(parent, SWT.CALENDAR); DateTime date = new DateTime(parent, SWT.DATE); DateTime time = new DateTime(parent, SWT.TIME); // Date Selection as a drop-down DateTime dateD = new DateTime(parent, SWT.DATE | SWT.DROP_DOWN); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } // tear down the SWT window display.dispose(); } }

Please note that the SWT
DateTime
widget requires a selection, i.e. you cannot use this widget without a
date selection.
Images can be displayed via labels. The following class demonstrates that using some system images.
package de.vogella.swt.widgets; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; public class Photo { public static void main(String[] args) { // setup the SWT window Display display = new Display(); final Shell shell = new Shell(display); shell.setLayout(new RowLayout()); shell.setText("Photo Application"); // initialize a parent composite with a grid layout manager // with 5x columns Composite parent = new Composite(shell, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 5; parent.setLayout(gridLayout); // Get the Display default icons List<Image> imageList = new ArrayList<Image>(); imageList. add(Display.getDefault().getSystemImage(SWT.ICON_WARNING)); imageList. add(Display.getDefault().getSystemImage(SWT.ICON_WORKING)); imageList. add(Display.getDefault().getSystemImage(SWT.ICON_QUESTION)); imageList .add(Display.getDefault().getSystemImage(SWT.ICON_INFORMATION)); imageList. add(Display.getDefault().getSystemImage(SWT.ICON_ERROR)); for (Image image : imageList) { Label label = new Label(parent, SWT.NONE); label.setImage(image); } // show the SWT window shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } // tear down the SWT window display.dispose(); // if you do not use system images you would have to release them // not necessary in this example // for (Image image : imageList) { // if (image != null) { // image.dispose(); // } // } } }
The result should look similar to the following.

Create the following class.
package de.vogella.swt.table; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; public class SWTTable { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout()); Table table = new Table(shell, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); table.setLinesVisible(true); table.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 200; table.setLayoutData(data); String[] titles = { "First Name", "Last Name", "Age" }; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); table.getColumn(i).pack(); } for (int i = 0 ; i<= 50 ; i++){ TableItem item = new TableItem(table, SWT.NONE); item.setText (0, "Person " +i); item.setText (1, "LastName " +i); item.setText (2, String.valueOf(i)); } for (int i=0; i<titles.length; i++) { table.getColumn (i).pack (); } shell.pack (); shell.open (); shell.open(); while (!display.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
If you run this application a table will be displayed.
Create the following class.
package de.vogella.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; public class TreeMenuTest { public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); final Tree tree = new Tree(shell, SWT.V_SCROLL); for (int i=0; i<5;i++) { TreeItem item = new TreeItem(tree, SWT.NONE); item.setText(String.valueOf(i)); for (int j=0; j<3;j++) { TreeItem subItem = new TreeItem(item, SWT.NONE); subItem.setText(String.valueOf(i) + " " + String.valueOf(j)); } } tree.pack(); Menu menu = new Menu(tree); MenuItem menuItem = new MenuItem(menu, SWT.NONE); menuItem.setText("Print Element"); menuItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { System.out.println(tree.getSelection()[0].getText()); } }); tree.setMenu(menu); shell.pack(); shell.open(); while (!display.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
If you run this application a tree will be display with a menu attached to it. If you select the menu the text of the selected item will be printed to the console.
CTabFolder and CTabItem allow to create the folder experience with different tabs.
package de.vogella.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class CTabFolderExample { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout()); // SWT.BOTTOM to show at the bottom CTabFolder folder = new CTabFolder(shell, SWT.BOTTOM); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); folder.setLayoutData(data); CTabItem cTabItem1 = new CTabItem(folder, SWT.NONE); cTabItem1.setText("Tab1"); CTabItem cTabItem2 = new CTabItem(folder, SWT.NONE); cTabItem2.setText("Tab2"); CTabItem cTabItem3 = new CTabItem(folder, SWT.NONE); cTabItem3.setText("Tab3"); Text text = new Text(folder, SWT.BORDER); text.setText("Hello"); cTabItem1.setControl(text); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
If you run this application you will see several register cards with
tabs on
them. The
SWT.BOTTOM
stylebit on the folder widget, makes the tab appear at the bottom.

Create the following class.
package de.vogella.swt.dnd; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import de.vogella.swt.dnd.MyDragSourceListener; import de.vogella.swt.dnd.MyDropTargetListener; public class PhotoShuffler { public static void main(String[] args) { // setup the SWT window Display display = new Display(); final Shell shell = new Shell(display); shell.setSize(520, 200); shell.setLayout(new RowLayout()); shell.setText("Photo Shuffler"); // initialize a parent composite with a grid layout manager // since the demo application uses 4x pictures the grid has exactly // 4x columns Composite parent = new Composite(shell, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 4; parent.setLayout(gridLayout); // determine the path where the pictures are stored String path = System.getProperty("user.dir") + "/images/"; // initialize an array with the photograph names String[] imgNames = new String[] { "lars.png", "andre.png", "matthias.png", "arne.png" }; // loop over the photo array and establish all listeners for (int i = 0; i < imgNames.length; i++) { // labels serve as containers for the images Label label = new Label(parent, SWT.NONE); Image img = new Image(display, path + imgNames[i]); label.setImage(img); // enable each label to be draggable DragSource source = new DragSource(label, DND.DROP_NONE); source.setTransfer(new Transfer[] { TextTransfer.getInstance() }); // add a drag listener source.addDragListener(new MyDragSourceListener(parent, source)); // enable each label to be a drop target DropTarget target = new DropTarget(label, DND.DROP_NONE); target.setTransfer(new Transfer[] { TextTransfer.getInstance() }); // add a drop listener target.addDropListener(new MyDropTargetListener(parent, target)); } // show the SWT window shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } // tear down the SWT window display.dispose(); } }
Create the following DragSource and DragTarget Listener.
package de.vogella.swt.dnd; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; public class MyDropTargetListener implements DropTargetListener { private Composite parentComposite; private DropTarget target;/** * @param parentComposite * - the composite that holds all pictures * @param target * - the drop target */public MyDropTargetListener(Composite parentComposite, DropTarget target) { this.parentComposite = parentComposite; this.target = target; } public void dragEnter(DropTargetEvent event) { } public void dragOver(DropTargetEvent event) { } public void dragLeave(DropTargetEvent event) { } public void dropAccept(DropTargetEvent event) { } public void dragOperationChanged(DropTargetEvent event) { }/** * This method moves the dragged picture to the new position and shifts the * old picture to the right or left. */public void drop(DropTargetEvent event) { // retrieve the stored index int sourceIndex = Integer.valueOf(event.data.toString()); // compute the index of target control Control targetControl = target.getControl(); int targetIndex = -1; for (int i = 0; i < parentComposite.getChildren().length; i++) { if (parentComposite.getChildren()[i].equals(targetControl)) { targetIndex = i; break; } } Control sourceControl = parentComposite.getChildren()[sourceIndex]; // do not do anything if the dragged photo is dropped at the same // position if (targetIndex == sourceIndex) return; // if dragged from left to right // shift the old picture to the left if (targetIndex > sourceIndex) sourceControl.moveBelow(targetControl); // if dragged from right to left // shift the old picture to the right else sourceControl.moveAbove(targetControl); // repaint the parent composite parentComposite.layout(); } }
package de.vogella.swt.dnd; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.widgets.Composite; public class MyDragSourceListener implements DragSourceListener { private Composite parentComposite; private DragSource source;/** * @param parentComposite * - the composite that holds all pictures * @param source * - the drag source * */public MyDragSourceListener(Composite parentComposite, DragSource source) { this.parentComposite = parentComposite; this.source = source; } public void dragStart(DragSourceEvent event) { } public void dragFinished(DragSourceEvent event) { }/** * The method computes the position / index of the source control (label) in * the children array of the parent composite. This index is passed to the * drop target using the data field of the drag source event. */public void dragSetData(DragSourceEvent event) { for (int i = 0; i < parentComposite.getChildren().length; i++) { if (parentComposite.getChildren()[i].equals(source.getControl())) { event.data = new Integer(i).toString(); break; } } } }
You can define a global keylistener on your display to listen globally to all key events as long as your application has focus. The following demonstrates this.
package de.vogella.swt.listener; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class GlobalListener { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.open(); display.addFilter(SWT.KeyDown, new Listener() { @Override public void handleEvent(Event event) { char c = event.character; System.out.println(c); } }); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } }
JFace is a set of APIs which builds on top of SWT and provides higher level abstraction APIs and commonly used functions. JFace extends the SWT API for certain uses case but does not hide it. Therefore you need a solid understanding of SWT if you work with JFace.
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
Understanding Layout in SWT by Wayne Beaton
Changing the position of the icon and text in a SWT Tree
vogella Training Android and Eclipse Training from the vogella team
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