Back to top

vogella training Training Books

SWT Tutorial

Lars Vogel

Version 2.5

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

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. What is SWT?
1.2. Display and Shell
1.3. Event loop
2. Using SWT
3. Using SWT in a plug-in project
4. Using SWT in a standard Java project
5. SWT Widgets
5.1. Overview
5.2. Memory management
5.3. Constructing widgets
5.4. Basic Containers
6. Event Listener
7. Example: Create plug-in project with dependency to SWT
8. Exercise: Create a simple SWT program
9. Label and Text
10. Exercise: SWT Button
11. Layout Manager in SWT
11.1. The role of a layout manager
11.2. Layout Data
11.3. FillLayout
11.4. RowLayout
11.5. GridLayout
12. Example: Layouts in SWT
13. Tab Order of elements
14. SWT Snippets, Examples and Nebula
15. DateTime widget
16. Image
17. Table
18. Tree and Menu
19. CTabFolder
20. Drag and Drop
21. Define a global keylistener for your Display
22. Relationship to JFace
23. Thank you
24. Questions and Discussion
25. Links and Literature
25.1. Source Code
25.2. Eclipse SWT Resources
25.3. vogella Resources

1. SWT Overview

1.1. What is SWT?

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.

1.2. Display and Shell

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.

1.3. Event loop

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.

2. Using SWT

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.

3. Using SWT in a plug-in project

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 

4. Using SWT in a standard Java project

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.

5. SWT Widgets

5.1. Overview

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.

5.2. Memory management

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.

5.3. Constructing widgets

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

5.4. Basic Containers

The Composite class is a container which is allowed to contain other widgets. The Group class is also a container which is allowed to contain other widget but it also draws a border around itself and allows you to set a header for the box.

6. Event Listener

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: Name Listener Name Adapter .

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

7. Example: Create plug-in project with dependency to SWT

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

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.

New Plug-in Projec Wizard Page 1

New Plug-in Projec Wizard Page 2

Press the Finish 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 Add button in the Required Plug-ins part and enter org.eclipse.swt as dependency.

Adding the dependency to SWT in the Plug-in project

8. Exercise: Create a simple SWT program

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

First running SWT application

9. Label and Text

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.

10. Exercise: SWT Button

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!");
    }
}); 

11. Layout Manager in SWT

11.1. The role of a layout manager

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.


11.2. Layout Data

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.

11.3. FillLayout

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.

11.4. RowLayout

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.

11.5. GridLayout

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.

12. Example: Layouts in SWT

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.

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

14. SWT Snippets, Examples and Nebula

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/

15. DateTime widget

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

Date Time Widget

Please note that the SWT DateTime widget requires a selection, i.e. you cannot use this widget without a date selection.

16. Image

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.

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

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

19. CTabFolder

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.

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

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

22. Relationship to JFace

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.

23. Thank you

Please help me to support this article:

Flattr this

24. 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.com Google Group. I have created a short list how to create good questions which might also help you.

25. Links and Literature

25.1. Source Code

Source Code of Examples

25.3. vogella Resources

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