Version 2.3
Copyright © 2010, 2011, 2012 Lars Vogel
01.02.2012
| Revision History | ||
|---|---|---|
| Revision 0.1 | 21.05.2010 | Lars Vogel |
| Started | ||
| Revision 0.2 - 2.3 | 24.05.2010 - 12.01.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; therefore the
SWT
API (Application Programming Interface)
is very close to the
native
API.
As the
SWT
API is very rudimentary, programmers typically also use
JFace.
JFace
is a set of APIs which builds on top of
SWT
and provides higher abstraction APIs.
JFace
does not hide the
SWT
API but extends it. Therefore it is important to
have a solid
understanding of
SWT,
even if JFace is used.
SWT
uses the native widgets of the
platform whenever possible. The native
widgets of
the OS are
accessed by the
SWT
framework via
JNI
(Java Native Interface).
SWT
is from its
design similar to the
AWT.
AWT
is 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.
SWT
emulates in this case the
unavailable widget. For
example
AWT
does not have table or tree widgets included, while
SWT
has.
The
Display
and the
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
basis for
all
SWT
capabilities
and can be seen as the model for
SWT.
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.
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. For example the
following creates a
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
Eclipse
Plug-ins
or
Eclipse RCP
application this event loop
is
handled by the
Eclipse
application.
It is possible to use
SWT
for standalone application. Alternatively you could use the UI
toolkits, AWT, Java Swing or JavaFX for your standalone Java
application.
If you programming Eclipse applications you typically use
SWT
for the user interface. But it is possible to use other UI toolkits,
e.g. JavaFX as user interface technology, 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 are extend the Eclipse IDE you
have to use
SWT
as the Eclipse IDE Workbench uses a
SWT
renderer.
To use
SWT
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.
The Eclipse IDE ships with the
SWT
library and you can use this in your project. Eclipse provides
plug-in projects, which allow to define dependency to libraries.
Eclipse uses itself (or more specifically the Target Platform defined
in the Eclipse Preference) to search for fitting libraries based on
your dependency definition. Eclipse finds the
SWT
library and adds the corresponding jar file to your project class
path.
This is a simple way for 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 file
located in the folder
META-INF.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Swt Bundle-SymbolicName: de.vogella.swt Bundle-Version: 1.0.0.qualifier Require-Bundle: org.eclipse.swt Bundle-RequiredExecutionEnvironment: JavaSE-1.6
If you don't want to use Eclipse plug-in capabilities you can download the SWT library from http://www.eclipse.org/swt/ . This zip file contains a "swt.jar" file which you need for the classpath of your SWT project.
SWT
widgets are contained in the packages
org.eclipse.swt.widgets
and
org.eclipse.swt.custom.
While
SWT
tries to use native widgets as much as possible it is
not possible
to
fulfill all requirements with the native widgets.
Therefore some
widgets extend
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.
CCombo
provides
compared to
Combo
the possibility 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
are using native code. Custom widgets are also 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.
Only for these base classes, API compliance is
guaranteed.
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. This will automatically release all its children.
The automatic release does not work for
Fonts,
Images
and
Color
objects. These SWT objects need to be manually disposed.
SWT
widgets, except
Shell,
are always constructed with a parent widget which
contains them. As
second parameter stylebits can be passed to the
widget.
Depending on the provided stylebits the widget adjusts its look and feel as well as its behavior. Each widget documents in its Javadoc its supported stylebits.
Stylebits are predefined via 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);
On components you can register a listener for specific events, e.g.
a
ModifyListener
to listen to changes in a Text field
or a
SelectionLister
for selection
(click) events.
button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // Handle the selection event } });
What kind of event listeners are available, depends on the user
interface
component.
ModifyListener,
FocusListener
and
SelectionListener.
Listeners
are examples for these listener interfaces.
Eclipse usually
provides for these interfaces a default implementation.
This follows usually a
→
naming scheme.
For
example
SelectionListener
has
the abstract class
SelectionAdapter
which pre-implements the methods of
SelectionListener.
Create a new plug-in project
com.examle.swt.widgets
via
→ → → → .
Fill out 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 finish on the second page of the wizard.
Open the file
MANIFEST.MF
in the folder "META-INF" and select the tab
"Dependencies".
Press add in the "Required Plug-ins" part and enter "org.eclipse.swt".

Create
the
following class to have 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); 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 your code to the following.
package com.example.swt.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class FirstSWTApplication { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); createUi(display, shell); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } private static void createUi(Display display, Shell shell) { 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 label"); text.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); text.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); // Resize widgets to there preferred size text.pack(); label.pack(); } }
If you now start the application you will get a small
Shell
with two
Widgets
included.

A layout manager is
responsible for arranging the UI components
of a
container (
Composite
)
on
the
screen.
SWT
offers several standard layout managers.
Table 1. Layout Manager
| Layout Manager | Description |
|---|---|
| AbsoluteLayout | Allows 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 | Layout equal-sized widgets in a single row or column. |
| RowLayout | Layout widgets in a row or rows, with fill, wrap, and spacing options. |
| GridLayout | Layouts widgets in a grid. |
| RowLayout | Layouts widgets by creating attachments for each of their sides. |
Each UI
element
can get layout specific elements
assigned to it via
data
element, e.g.
GridData
for a
GridLayout. For example you can
specify that a certain UI component 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 fit to the used
LayoutManager
otherwise the runtime will throw an exception.
The layout will be automatically calculated. You can tell a
Composite
to calculate the layout with the
composite.layout()
method.
FillLayout
divides the available space equally to all widgets and can be set to
arrange the widgets either
horizontally(
SWT.HORIZONTAL
)
or vertically (
SWT.VERTICAL
). It also allows 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 per default wrapping of
fields (field
wrap
). 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.
The following will demonstrate the usage of
GridLayout
.
GridData
objects should not be re-used, as the
GridLayout
expects that every UI
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
GridData(horizontalAlignment,verticalAlignment,
grabExcessHorizontalSpace, grabExcessVerticalSpace, horizontalSpan,
verticalSpan)
constructor.
The parameters / attributes define the following.
Table 2. GridData
| Parameter | Description |
|---|---|
| horizontalAlignment |
how control will be positioned horizontally
within a
cell,
one of:
SWT.BEGINNING
(same as
SWT.LEFT
),
SWT.CENTER,
SWT.END
(same as
SWT.RIGHT
), or
SWT.FILL
|
| verticalAlignment |
how control will
be positioned vertically within a
cell,
one of:
SWT.BEGINNING
(or
SWT.TOP
),
SWT.CENTER,
SWT.END
(same as
SWT.BOTTOM
), or
SWT.FILL
|
| grabExcessHorizontalSpace | whether cell will be made wide enough to fit the remaining horizontal space |
| grabExcessVerticalSpace | whether cell will grab 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 |
To test GridLayout create the following class in your
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 no need // to be 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 lable"); 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(GridData.FILL, GridData.BEGINNING, 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(GridData.FILL, GridData.BEGINNING, 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(GridData.END, GridData.BEGINNING, 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 changes.
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 Snippet site located under the URL:
http://www.eclipse.org/swt/snippets/. These snippets
gives examples for
stand-alone
SWT
applications using different kinds of SWT widgets.
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.
In addition the Eclipse Nebula project provides additional widgets for SWT. The homepage can be found under the URL: http://eclipse.org/nebula/
SWT provides new 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.setSize(520, 200); shell.setLayout(new RowLayout()); // initialize a parent composite with a grid layout manager // since the demo application uses 4x pictures the grid has exactly // 4x columnsxample 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); // show the SWT window shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } // tear down the SWT window display.dispose(); } }

Image 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 // 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 = 7; parent.setLayout(gridLayout); // Get the Display default icons List<Image> imageList = new ArrayList<Image>(); imageList.add(Display.getDefault().getSystemImage(SWT.ICON_CANCEL)); 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_SEARCH)); imageList .add(Display.getDefault().getSystemImage(SWT.ICON_INFORMATION)); imageList.add(Display.getDefault().getSystemImage(SWT.ICON_ERROR)); // Alternative load images via // Image img = new Image(display, path + imgNames[i]); // to get a path // String path = System.getProperty("user.dir") + "/images/"; 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(); } }
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 notebook 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(GridData.FILL, GridData.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(); shell.open(); while (!display.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
If you run this application you show see several register cards with
tabs on them. The
SWT.BOTTOM
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(); } } }
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.
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