by Lars Vogel

Follow me on twitter

Lars Vogel on Google+

SWT Tutorial

Lars Vogel

Version 2.3

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

SWT

This tutorial describes SWT the user interface toolkit used by the Eclipse IDE. This article was written using Eclipse 4.2 (Juno).


Table of Contents

1. SWT Overview
1.1. Overview
1.2. Display and Shell
1.3. Event loop
2. Using SWT
3. Making SWT available
3.1. SWT
3.2. Plug-in project
3.3. Manually adding the SWT library
4. SWT Widgets
4.1. Widgets
4.2. Memory management
4.3. Constructing widgets
4.4. Composites and Groups
5. Event Listener
6. SWT Shell with Label and Text
7. Layout Manager in SWT
7.1. Overview
7.2. Layout Data
7.3. FillLayout
7.4. RowLayout
7.5. GridLayout
8. Layouts in SWT
9. Tab Order of elements
10. SWT Snippets and Nebula
11. DateTime Widgets
12. Image
13. Table
14. Tree and Menu
15. CTabFolder
16. Drag and Drop
17. Define a global keylistener for your Display
18. Thank you
19. Questions and Discussion
20. Links and Literature
20.1. Source Code
20.2. Eclipse SWT Resources
20.3. vogella Resources

1. SWT Overview

1.1. Overview

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.

1.2. Display and Shell

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.

1.3. Event loop

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.

2. Using SWT

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.

3. Making SWT available

3.1. SWT

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.

3.2. Plug-in 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

			

3.3. Manually adding the SWT library

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.

4.  SWT Widgets

4.1. Widgets

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.

4.2.  Memory management

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.

4.3. Constructing widgets

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);
			

4.4. Composites and Groups

A Composite is a container which allows to contain other widgets. A Group is also a container which allows to contain other widgets; in addtion it draws a border around itself and allows to set a header for the box.

5. Event Listener

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 NameInterfaceNameAdapter naming scheme. For example SelectionListener has the abstract class SelectionAdapter which pre-implements the methods of SelectionListener.

6. SWT Shell with Label and Text

Create a new plug-in project com.examle.swt.widgets via FileNewOtherPlug-in DevelopmentNew Plug-in Project.

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.

New Plug-in Projec Wizard Page 1

New Plug-in Projec Wizard Page 2

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".

Adding the dependency to SWT in the Plug-in project

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 Run-AsJava Application. 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.

7.  Layout Manager in SWT

7.1.  Overview

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.


7.2.  Layout Data

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.

7.3.  FillLayout

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.

7.4.  RowLayout

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.

7.5.  GridLayout

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


8. Layouts in SWT

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.

9.  Tab Order of elements

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();
			}
		}
	}
}

		

10. SWT Snippets and Nebula

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/

11.  DateTime Widgets

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();
	}
}

		

Date Time Widget

12. Image

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.

13.  Table

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.

14.  Tree and Menu

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.

15.  CTabFolder

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.

16.  Drag and Drop

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; } } } }

17.  Define a global keylistener for your Display

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();
		}
	}
}

		

18. Thank you

Please help me to support this article:

Flattr this

19. 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.

20. Links and Literature

20.1. Source Code

Source Code of Examples

20.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