32
SWT (Standard Widget Toolkit) TUTORIAL By Kalman Hazins ([email protected])

6 swt programming

Embed Size (px)

DESCRIPTION

keep following me guys

Citation preview

Page 1: 6 swt programming

SWT (Standard Widget Toolkit) TUTORIAL

By Kalman Hazins

([email protected])

Page 2: 6 swt programming

Agenda

Brief History of Java GUI

Installing SWT

Creating widgets

SWT Layouts

Event Handling

Sample Application

Page 3: 6 swt programming

History of Java GUI

AWT – Abstract Windowing Toolkit

First released in 1995 as part of JDK 1.0 by Sun

Heavyweight GUI components – a Java component creates a peer

component on the operating system and the peer draws itself.

Least Common Denominator problem – for simple GUI components

creating a peer works, what about the components that are only

available on some platforms and not others? If you want to write code

that’s truly portable – you have to use components that are available on

all platforms

The logic makes sense – but how do you develop a serious application

using just the basic components (available on all platforms)?

You don’t …

Enter Swing

Page 4: 6 swt programming

History of Java GUI (Cont.)

Swing (JFC – Java Foundation Classes)

Released in 1998 as part of JDK 1.1

Lightweight GUI components – no need for operating system

“peer”-based drawing. Let’s draw the components ourselves.

Lightweight – there is no actual weight (operating system

component) behind the Java component.

Nice toolkit with enhanced Model-View-Controller architecture

and superior graphics 2D library.

Portable? You bet. Any problems? Now that you are not actually

using the operating system components – you are just mimicking

the behavior of the operating system. Hence, the look and feel

as well as the response speed are not the same.

Swing got much better over time

Still, very few commercial applications are written in Swing.

Page 5: 6 swt programming

History of Java GUI (Cont.)

SWT (Standard Widget Toolkit)

GUI toolkit released in November 2001

Was initially designed to write the now extremely famous and

popular Eclipse IDE

“Best of both worlds” approach – use native functionality when

available, and Java implementation when unavailable

Takes on the appearance and behavior of the native platform

Because of its close bond with the operating system, SWT

needs to be ported separately for every platform

Currently, implementations of SWT are already available for all

major desktop operating systems and some handheld devices

The code YOU write will be portable for all the platforms that

have SWT implementations for them (unless you decide to do

some platform specific stuff like OLE on windows)

http://www.eclipse.org/swt/ - SWT home page

Page 6: 6 swt programming

Installing SWT

To compile and run SWT applications you need

1. SWT jars (usually just swt.jar)

2. SWT native libraries

Detailed Instructions on obtaining and “installing”1. Go to http://www.eclipse.org/swt and follow one of the many

mirror links

2. This will bring you to another page, where you want to follow the “Latest Release” link

3. This should bring you to a page which will say “Release Build: “ in bold letters on the very top

4. Scroll down to the bottom of the page till you see “SWT Binary and Source” section

5. Pick the platform you intend to develop on from the list (e.g. Windows XP) and click on “(http)” to start downloading the zip file

6. Extract the contents of the zip file into a directory and you are ready for the final step(s) (let’s say our directory path is C:\SWT)

Page 7: 6 swt programming

Installing SWT (Cont.)

7. You need to include swt.jar (and possibly other jars) from the C:\SWT folder in your classpath (for an example on setting classpath see http://www.moreservlets.com/Using-Tomcat-4.html#Set-CLASSPATH)

8. You also need to include the native library files (e.g. *.dll) from C:\SWT in your java.library.path.

a. The easiest way to do this one is to execute the following command from a regular java program

System.out.println(System.getProperty(“java.library.path”));

which will give you a list of the directories in your “library path”. You can then copy the native library files from C:\SWT to one of those directories.

-OR-

b. Simply provide the path when running java

java –Djava.library.path=C:\SWT classname

Page 8: 6 swt programming

Creating Widgets

SWT Javadoc - http://www.jlab.net/eclipse/doc/3.1/index.html

Simplest SWT program (explained over the next few slides)

1. import org.eclipse.swt.widgets.*;

2. import org.eclipse.swt.widgets.Shell;

3. public class HelloWorld {

4. public static void main(String[] args) {

5. Display display = new Display();

6. Shell shell = new Shell(display);

7. shell.setText("Hello World");

8. shell.setSize(250, 100);

9.

10. shell.open();

11.

12. while (!shell.isDisposed()) {

13. if (!display.readAndDispatch()) {

14. display.sleep();

15. }

16. }

17. display.dispose();

18. }

19. }

Page 9: 6 swt programming

Creating Widgets (Cont.)

Think of Shell object (line 6) being almost the same as a JFrame in Swing, i.e. the highest-level container, which contains other widgets (e.g. buttons, labels etc.) inside of it

Unlike Swing

1. You need to create Display object (line 5), which represents the underlying windowing system. This in turn serves as a parent to the Shell. (In SWT, every widget you create will always have its parent passed into the widget’s constructor.)

2. You need to keep the Shell open to listen for events with a while loop (lines 12-16). Otherwise, the Shell will immediately close itself.

3. Since you are not just writing some Java code (having the luxury of garbage collector clean up after you), but are actually requesting some heavyweight resources from the underlying platform – you need to dispose of those resources when you are done with them(line 17). (Luckily, disposing of the parent disposes of its child, so 99% of time you will not be running around disposing of widgets right and left.)

If you are a Swing guy, and the above 3 things greatly bother you – you can write a simple SWTUtil class to help you deal with it …

Page 10: 6 swt programming

Homegrown SWT Utility

SWTUtil.java

import org.eclipse.swt.widgets.*;

public class SWTUtil {

private static Display display = new Display();

public static Shell getShell() {

Shell shell = new Shell(display);

return shell;

}

public static void openShell(Shell shell) {

shell.open();

// This loop keeps the shell open constantly listening for events

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) {

display.sleep();

}

}

display.dispose();

}

}

Page 11: 6 swt programming

SWT Utility in Action

“Simplest SWT program” rewritten

using SWTUtil class

import org.eclipse.swt.widgets.*;

public class HelloWorld {

public static void main(String[] args) {

Shell shell = SWTUtil.getShell();

shell.setText(“Still Hello World");

shell.setSize(250, 100);

SWTUtil.openShell(shell);

}

}

Page 12: 6 swt programming

Widget creation explained

A widget in SWT is created by

1. Specifying parent

2. Specifying style

A parent is the container that the widget is created inside of (e.g.

Shell).

Style is any constant from the SWT class (SWT.PUSH,

SWT.BORDER, SWT.LEFT etc).

All styles applicable to the widget can be found in the Javadoc for

that widget (as well as its superclasses if any).

If more than one style is desired – separate them out with a “|”

bitwise operator (e.g. SWT.MULTI |

SWT.V_SCROLL|SWT.H_SCROLL| SWT.BORDER creates a multiline

textarea that has vertical and horizontal scrollbars and a border

around it). If no specific style is desired – use SWT.NONE. The style

you are requesting is only a hint, so if the underlying platform

doesn’t support it – you are out of luck.

Page 13: 6 swt programming

Label

Unselectable, uneditable text

SWT.VERTICAL or SWT.HORIZONTAL can be used together with

SWT.SEPARATOR to create a label that is a horizontal/vertical separator

LabelWorld.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class LabelWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("Label World");

8. shell.setLayout(new GridLayout()); // layouts are explained later

9.

10. // Create labels

11. new Label(shell, SWT.NONE).setText("Regular label");

12. new Label(shell, SWT.SEPARATOR);

13. new Label(shell, SWT.SEPARATOR|SWT.HORIZONTAL);

14.

15. // pack and show

16. shell.pack();

17. SWTUtil.openShell(shell);

18. }

19. }

Page 14: 6 swt programming

Button

Once a button – always a button. All types of buttons are created using the Button class. Push buttons, radio buttons, check buttons, toggle buttons and even flat buttons.

ButtonWorld.java

1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class ButtonWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("Button World");

8. shell.setLayout(new GridLayout(2, true)); // layouts are explained later

9.

10. new Button(shell, SWT.PUSH | SWT.FLAT).setText("Flat Push Button");

11. new Button(shell, SWT.CHECK).setText("Check Button");

12. new Button(shell, SWT.TOGGLE).setText("Toggle Button");

13. new Button(shell, SWT.RADIO).setText("Radio Button");

14.

15. // pack and show

16. shell.pack();

17. SWTUtil.openShell(shell);

18. }

19. }

Page 15: 6 swt programming

Text Different types of text widgets are created using Text class by providing the

appropriate styles

TextWorld.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class TextWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("Text World");

8. shell.setLayout(new GridLayout()); // layouts are explained later

9.

10. new Text(shell, SWT.NONE).setText("Missing something ...");

11. new Text(shell, SWT.BORDER); // regular textfield

12. new Text(shell, SWT.PASSWORD | SWT.BORDER).setText("password");

13. new Text(shell, SWT.READ_ONLY | SWT.BORDER).setText("Can't type inside");

14. new Text(shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP

15. | SWT.BORDER).setText("\n\n\n");

16.

17. // pack and show

18. shell.pack();

19. SWTUtil.openShell(shell);

20. }

21. }

Page 16: 6 swt programming

List Pick from a list – single or multiple selection available

ListWorld.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class ListWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("List World");

8. shell.setLayout(new GridLayout(2, true)); // layouts are explained later

9.

10. String[] items = "One Two Three Four Five Six".split(" ");

11. List one = new List(shell, SWT.SINGLE | SWT.BORDER);

12. one.setItems(items);

13. one.select(2);

14. List two = new List(shell, SWT.MULTI | SWT.BORDER);

15. two.setItems(items);

16. two.setSelection(items);

17.

18. // pack and show

19. shell.pack();

20. SWTUtil.openShell(shell);

21. }

22. }

Page 17: 6 swt programming

Combo

Benefits of both Text and List widgets in one!

ComboWorld.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class ComboWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("Combo World");

8. shell.setLayout(new GridLayout(3, true)); // layouts are explained later

9.

10. String[] items = "One Two Three Four Five Six".split(" ");

11. Combo one = new Combo(shell, SWT.DROP_DOWN);

12. one.setItems(items);

13. Combo two = new Combo(shell, SWT.DROP_DOWN | SWT.READ_ONLY);

14. two.setItems(items);

15. Combo three = new Combo(shell, SWT.SIMPLE);

16. three.setItems(items);

17.

18. // pack and show

19. shell.pack();

20. SWTUtil.openShell(shell);

21. }

22. }

Page 18: 6 swt programming

Group Used to group widgets together. (Very similar to JPanel in Swing)

GroupWorld.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.GridLayout;

3. import org.eclipse.swt.widgets.*;

4. public class GroupWorld {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("Group World");

8. shell.setLayout(new GridLayout()); // layouts are explained later

9.

10. Group buttonGroup = new Group(shell, SWT.SHADOW_OUT);

11. buttonGroup.setText("Six buttons");

12. buttonGroup.setLayout(new GridLayout(3, true));

13. for(int i = 0; i < 6; i++) {

14. new Button(buttonGroup, SWT.RADIO).setText("Bottle " + (i + 1));

15. }

16.

17. // pack and show

18. shell.pack();

19. SWTUtil.openShell(shell);

20. }

21. }

Page 19: 6 swt programming

Browser

One of the newer widgets of SWT for displaying web content.

Cool stuff!!! (See the sample application later)

BrowserWorld.java

1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.browser.Browser;

3. import org.eclipse.swt.layout.FillLayout;

4. import org.eclipse.swt.widgets.Shell;

5. public class BrowserWorld {

6. public static void main(String[] args) {

7. Shell shell = SWTUtil.getShell();

8. shell.setText("Browser World");

9. shell.setLayout(new FillLayout());

10.

11. Browser browser = new Browser(shell, SWT.BORDER);

12. browser.setSize(900, 500);

13. browser.setUrl("http://www.eclipse.org/swt/");

14.

15. // pack and show

16. shell.pack();

17. SWTUtil.openShell(shell);

18. }

19. }

Page 20: 6 swt programming

Browser in Action

Page 21: 6 swt programming

SWT Layouts

Layouts first introduced in AWT

Ease burden of laying out components

Promote cross-platform GUI design

SWT offers 5 layouts:

1. FillLayout

2. RowLayout

3. StackLayout

4. GridLayout

5. FormLayout

You set the composite’s layout by calling setLayout()

You don’t have to use a layout, but do you really want your widgets to

disappear when the user resizes the window?

More on layouts http://www.eclipse.org/articles/Understanding%20Layouts/Understanding%20Layouts.htm

Page 22: 6 swt programming

FillLayout

Places all widgets in either a single column or a single row depending on if SWT.VERTICAL or SWT.HORIZONTAL is used

Makes all widgets the same size

FillLayoutExample.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.FillLayout;

3. import org.eclipse.swt.widgets.*;

4. public class FillLayoutExample {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("FillLayoutExample");

8. shell.setLayout(new FillLayout(SWT.HORIZONTAL));

9.

10. for(int i = 0; i < 3; i ++) {

11. new Button(shell, (i % 2 == 0) ? SWT.RADIO : SWT.PUSH).setText("Button " + i);

12. new Text(shell, SWT.BORDER).setText("same size");

13. }

14.

15. // pack and show

16. shell.pack();

17. SWTUtil.openShell(shell);

18. }

19. }

Page 23: 6 swt programming

RowLayout Similar to FillLayout - places all widgets in either a single column or a single row depending on if SWT.VERTICAL

or SWT.HORIZONTAL is used

Doesn’t force all widgets to be the same size

Can wrap to a new row or column if it runs out of space

Can use RowData objects to determine initial heights/widths for controls

RowLayoutExample.java

1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.RowData;

3. import org.eclipse.swt.layout.RowLayout;

4. import org.eclipse.swt.widgets.*;

5. public class RowLayoutExample {

6. public static void main(String[] args) {

7. Shell shell = SWTUtil.getShell();

8. shell.setText("RowLayoutExample");

9. shell.setLayout(new RowLayout(SWT.HORIZONTAL));

10.

11. for(int i = 0; i < 3; i ++) {

12. new Button(shell, (i % 2 == 0) ? SWT.RADIO : SWT.PUSH).setText("Button " + i);

13. new Text(shell, SWT.BORDER).setLayoutData(new RowData(5, 50));

14. }

15.

16. // pack and show

17. shell.pack();

18. SWTUtil.openShell(shell);

19. }

20. }

Page 24: 6 swt programming

StackLayout

Similar to CardLayout in Swing. The basic idea is that all widgets are stacked on top of each other and you can only see one at a time.

Need to set topControl attribute for the layout to show any widget on top

Need to call layout() on the Composite every time you reassign topControl

StackLayoutExample.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.custom.StackLayout;

3. import org.eclipse.swt.events.*;

4. import org.eclipse.swt.widgets.*;

5. public class StackLayoutExample {

6. public static void main(String[] args) {

7. final Shell shell = SWTUtil.getShell();

8. shell.setText("RowLayoutExample");

9. shell.setLayout(new StackLayout());

10.

11. final Button button1 = new Button(shell, SWT.PUSH);

12. button1.setText("Button One");

13. final Button button2 = new Button(shell, SWT.PUSH);

14. button2.setText("Button Two");

15. class StackLayoutAdapter extends SelectionAdapter {

16. public void widgetSelected(SelectionEvent event) {

17. ((StackLayout)shell.getLayout()).topControl =

18. (event.widget == button1) ? button2 : button1;

19. shell.layout();

20. }

21. }

22. button1.addSelectionListener(new StackLayoutAdapter());

23. button2.addSelectionListener(new StackLayoutAdapter());

24.

25. ((StackLayout)shell.getLayout()).topControl = button1;

26. shell.pack();

27. SWTUtil.openShell(shell);

28. }

29. }

Page 25: 6 swt programming

GridLayout

Lays out controls in a grid.

A lot of people love this powerful layout.

You can easily specify what you want to happen when the composite is resized

6 attributes (defaults are preset):

1. int horizontalSpacing – horizontal space in pixels between adjacent cells

2. int verticalSpacing – vertical space in pixels between adjacent cells

3. boolean makeColumnsEqualWidth – forces all columns to be same width

4. int marginWidth – margin in pixels along right and left edges

5. int marginHeight – margin in pixels along top and bottom edges

6. int numColumns – number of columns for the layout

GridLayout(int numColumns, boolean makeColumnsEqualWidth)

Uses GridData objects to provide for better control

Too many options to list …

Warning for Swing programmers – DO NOT TRY TO REUSE GridData objects

Instead, you need to create a new GridData object for every widget that needs non-default behavior

Page 26: 6 swt programming

GridLayoutExample.java

1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.layout.*;

3. import org.eclipse.swt.widgets.*;

4. public class GridLayoutExample {

5. public static void main(String[] args) {

6. Shell shell = SWTUtil.getShell();

7. shell.setText("GridLayoutExample");

8. shell.setLayout(new GridLayout(2, false)); // 2 columns, same width

9.

10. // Username

11. new Label(shell, SWT.RIGHT).setText("Username:");

12. Combo cmbUsername = new Combo(shell, SWT.DROP_DOWN);

13. cmbUsername.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

14. cmbUsername.setItems(new String[]{"Howard", "Admin", "Kalman"});

15. cmbUsername.setText("Admin");

16.

17. // Password

18. new Label(shell, SWT.RIGHT).setText("Password:");

19. new Text(shell, SWT.BORDER | SWT.PASSWORD).GridData(GridData.FILL_HORIZONTAL));

20.

21. // Login Button

22. Button loginButton = new Button(shell, SWT.PUSH | SWT.FLAT);

23. loginButton.setText("Proceed to your account");

24. GridData data = new GridData(GridData.FILL_HORIZONTAL);

25. data.horizontalSpan = 2; // span 2 columns

26. loginButton.setLayoutData(data);

27. shell.pack();

28. SWTUtil.openShell(shell);

29. }

30. }

Page 27: 6 swt programming

FormLayout

Considered the most complex layout of SWT

Based on y = ax + b (not that most people who use it care)

MAXIMUM flexibility

People who understand it – love it

The basic idea is that you layout the widgets relative to each other or to the enclosing

composite

Needs a tutorial of its own and is therefore not covered here …

Page 28: 6 swt programming

Event Handling

If you are familiar with Swing – this last part should be a joke.

SWT widgets can listen for events to happen.

If you would like to hear when and what they hear – you need to attach a listener to

the widget

Listener is basically an interface that defines when certain behaviors happen

Sometimes, listener tries listening out for two many things, but you only care to listen

for one particular event

In such a case – you need an adapter. Adapter is a class that implements the

interface and from which you can just extend and override the method you are

interested in.

Some of the popular listeners/adapters are listed below

FocusListener/FocusAdapter – listens for focus gained and focus lost events

KeyListener/KeyAdapter – listens for key releases and key presses

ModifyListener(only has 1 method) – listens for text modifications

VerifyListener – listens for (and potentially intercepts) text modifications

MouseListener/MouseAdapter – listens for mouse button presses

SelectionListener/SelectionAdapter – listens for selection events (similar to

ActionListener in Swing)

Page 29: 6 swt programming

EventHandling.java1. import org.eclipse.swt.SWT;

2. import org.eclipse.swt.events.*;

3. import org.eclipse.swt.layout.*;

4. import org.eclipse.swt.widgets.*;

5. public class EventHandling {

6. private static boolean numbersOnly;

7. public static void main(String[] args) {

8. Shell shell = SWTUtil.getShell();

9. shell.setText("EventHandling");

10. shell.setLayout(new GridLayout(2, false));

11.

12. // input

13. Label lblInput = new Label(shell, SWT.RIGHT);

14. lblInput.setText("Type in here:");

15. GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);

16. lblInput.setLayoutData(data);

17. Text input = new Text(shell, SWT.BORDER);

18. input.addVerifyListener(new VerifyListener() {

19. public void verifyText(VerifyEvent vEvent) {

20. vEvent.doit = false; // don't allow anything but numbers

21. if(!numbersOnly || vEvent.character == '\b') {

22. vEvent.doit = true;

23. }

24. else if(Character.isDigit(vEvent.character) && numbersOnly) {

25. vEvent.doit = true;

26. }

27. }

28. });

Page 30: 6 swt programming

EventHandling.java

29. Button btnAllow = new Button(shell, SWT.CHECK);

30. btnAllow.setText("Allow numbers only");

31. data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);

32. data.horizontalSpan = 2;

33. btnAllow.setLayoutData(data);

34. btnAllow.addSelectionListener(new SelectionAdapter() {

35. public void widgetSelected(SelectionEvent selectionEvent) {

36. numbersOnly = ((Button)(selectionEvent.widget)).getSelection();

37. }

38. });

39. shell.pack();

40. SWTUtil.openShell(shell);

41. }

42. }

Page 31: 6 swt programming

syncExec() / asyncExec() You should only be updating user interfaces from the user interface thread.

For example, say you create a Label in your main thread. Then, you have a separate thread that does some sort of a long computation. Then, you want to update your label with the result of the second thread’s computation. You CANNOT just call label.setText(newValue) in your second thread.

Instead, you have to call either syncExec(Runnable) or asyncExec(Runnable) methods on the instance of Display

// Say you run a thread that calculates new time approximately every second

// and tries to update a label

new Thread(new Runnable() {

public void run() {

Display display = shell.getDisplay();

while(!shell.isDisposed()) {

try {

display.asyncExec(new Runnable() {

public void run() {

clock.setText((new Date()).toString());

}

});

Thread.sleep(1000);

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

Page 32: 6 swt programming

Sample Application

Goal: Write a cute browser in SWT (under

300 lines) that handles most HTML

CuteBrowser.java uses SWTUtil.java

Run the application on Windows XP

computer that has java installed