Graphics
SWT provides a graphics engine for drawing graphics and displaying
images in widgets. You can get pretty far without ever programming to the
graphics interface, since widgets handle the painting of icons, text, and other
data for you. However, if your application displays custom graphics, or if
you are implementing a custom drawn widget, then you will need to understand
some basic drawing objects in SWT.
Graphics context
The graphics context,
GC
,
is the focal point for SWT graphics support. Its API describes all of the
drawing capabilities in SWT.
A GC can be used for drawing on a control (the most common case), on an image,
on a display, or to a printer. When drawing on a control, you use the GC
supplied to you in the control's paint event. When drawing on an image,
display, or printer, you must create a GC configured for it, and dispose of the
GC when you are finished using it.
Once you've got a GC, you can set its attributes, such as color, line width, and font, which control
the appearance of the graphics drawn in the GC.
The API Reference for
GC
describes the complete set of graphics functions.
Fonts
The
Font
and
FontData
classes are used when manipulating fonts in SWT.
FontData describes the characteristics of a font. You can create a FontData
by specifying a font name, style, and size. FontData includes API for querying
these attributes. Since FontData does not allocate any OS resources, you do not
need to dispose of it.
The Font is the actual graphic object representing a font that is used in the
drawing API. You create a Font for a
Display
by specifying the Display and the FontData of the font that you want. You can
also query a Font for its FontData.
You must dispose of an allocated Font when you are finished using it.
Colors
Colors are similar to fonts. You create a
Color
for a Display by specifying the RGB values for the desired color. You must dispose of an
allocated color when you are finished using it.
The Display method getSystemColor(int)
allows you to query the predefined
system colors for the OS platform. You should not free colors obtained using
this technique.
The color model is discussed in detail in the article
SWT color model.
Images
The
Image
,
ImageData
, and
ImageLoader
classes are used when manipulating Images in SWT.
ImageData describes the actual pixels in the image, using the
PaletteData
class to describe the utilized color values. ImageData is a device- and
platform-independent description of an image.
ImageLoader loads and saves ImageData in different file formats. SWT
currently supports loading and saving of image formats including BMP
(Windows Bitmap), ICO (Windows Icon), JPEG, GIF, and
PNG.
The Image is the actual graphic object representing the image that is used
in the drawing API. You create an image for a particular Display. Images can
be created in several ways:
- use an ImageData to initialize the image's contents
- copy an existing Image
- load an Image from a file
Regardless of how you create the Image, you are responsible for disposing
it.
Graphics object lifecycle
Most of the graphics objects used for drawing in SWT allocate resources in
the underlying OS and must be explicitly freed. The same rule discussed earlier
applies here. If you create it using a constructor, you should free it. If you
get access to it from somewhere else, do not free it.
Creation
Graphics objects such as graphics contexts, fonts, colors, and images are
allocated in the OS as soon as the object is created. How you plan to use your
graphics objects determines when you should create them.
For graphics objects that are used heavily throughout the application, you
can create them at the time that you create your widgets. This is commonly
done for colors and fonts. In other cases, it is more appropriate to create
your graphics objects on the fly. For example, you might create a graphics
context in one of your widget event handlers in order to perform some
calculations.
If you are implementing a custom widget, you typically allocate graphics
objects in the constructor if you always make use of them. You might allocate
them on the fly if you do not always use them or if they are dependent upon
the state of some attribute.
Painting
Once you have allocated your graphics objects, you are ready to paint.
You should always do your painting inside of a paint listener. There
are rare cases, particularly when implementing custom widgets, when you paint
while responding to some other event. However this is generally discouraged.
If you think you need to paint while handling some other event, you should
first try to use the redraw() method, which will generate
another paint event in the OS. Drawing outside of the paint method defeats
platform optimizations and can cause bugs depending upon the number of pending
paints in the event queue.
When you receive a paint event, you will be supplied with a
GC
pre-configured for drawing in the widget. Do not free this
GC
!
You did not create it.
Any other graphics objects must be allocated while handling the event (or
beforehand). Below is a snippet based on the
org.eclipse.swt.examples.HelloWorld5 sample. The color red was
previously allocated when creating the widget, so it can be used here.
shell.addPaintListener (new PaintListener () {
public void paintControl (PaintEvent event) {
GC gc = event.gc;
gc.setForeground (red);
Rectangle rect = event.widget.getClientArea ();
gc.drawRectangle (rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20);
gc.drawString (resHello.getString("Hello_world"), rect.x + 20, rect.y + 20);
}
});
Disposal
Every graphics object that you allocate must be freed when you are finished
using it.
The timing of the disposal depends upon when you created the object. If you
create a graphics object while creating your widget, you should generally add
a dispose listener onto the widget and dispose of the graphics when the widget
is disposed. If you create an object on the fly while painting, you should
dispose of it when finished painting.
The next code snippet shows a slightly modified version of our paint listener.
In this example, it allocates and frees the color red while painting.
shell.addPaintListener (new PaintListener () {
public void paintControl (PaintEvent event) {
GC gc = event.gc;
Color red = new Color (event.widget.getDisplay (), 0xFF, 0, 0);
gc.setForeground (red);
Rectangle rect = event.widget.getClientArea ();
gc.drawRectangle (rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20);
gc.drawString (resHello.getString ("Hello_world"), rect.x + 20, rect.y + 20);
red.dispose ();
}
});