Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Drawing directly on a screen

Every class that extends the Field class has a paint() method. The paint() method determines how a field draws its contents. For classes that are included in the BlackBerry Java SDK, paint() is implemented in the class itself. For example, prebuilt UI components such as buttons and drop-down lists have paint() methods that describe how to draw the contents of the component, such as the text of the button or the items in the drop-down list. For classes that you create for custom UI components, you implement paint() to specify how to draw the component.

To draw on the screen of a BlackBerry device directly, you must override paint() of the Screen object that you want to draw on. The paint() method receives a Graphics object as a parameter, which represents the surface of a field that your application can draw on. You can then use the methods of the Graphics class, which is included in the net.rim.device.api.ui package, to draw content on the screen, such as shapes, text, and graphics. The Graphics object that paint() receives contains state information that is required for rendering operations, such as the current font and drawing color.

Context stack

BlackBerry device applications that have a UI include one or more objects that extend the Screen class, and each of these objects represents a separate screen in the application. An application maintains one Graphics object per screen, and managers and other fields use this Graphics object to draw the contents of the fields. Each Graphics object contains an internal context stack that stores information about the area that a field should draw in. The context stack includes information such as clipping region (the boundaries of the area to draw in) and drawing offset (the position of the area to draw in).

When a field is directed to draw itself and its contents, such as when the field is added to a screen or receives the focus, the field's manager pushes a transformation on to the context stack of the screen's Graphics object. The transformation provides information that determines how the field should be drawn on the screen. For example, the clipping region is defined as the dimensions of the field, so that the field can draw content only within the boundaries of the field. Similarly, the drawing offset is defined as the position of the field relative to the manager. The manager then passes the Graphics object, with its updated context stack, to the field that is being drawn. The field's paint() method uses the Graphics object to draw content in the proper position on the screen.

A transformation is pushed on to the context stack using the coordinates of the parent object. For example, a manager pushes a transformation that contains coordinates relative to the manager, instead of relative to any of the fields that the manager contains. Thus, the paint() methods of each field can use local coordinates, with the upper-left corner of the field represented as (0, 0), when drawing. The coordinates are translated back up through the transformations in the context stack to appear correctly on the screen.

You can push a new context on to the context stack of a Graphics object by invoking pushContext() of the Graphics class. Similarly, you can pop off the last pushed context stack by invoking popContext(). You can use these methods to create custom drawing areas on your screens.

Drawing shapes

You can use the methods of the Graphics class to draw primitive shapes on the screen of a BlackBerry device, including the following methods:

  • drawEllipse()
  • drawRect()
  • drawArc()

These methods draw outlines of their respective shapes, without any fill. You can use corresponding fill methods (such as fillEllipse(), fillRect(), and fillArc()) to draw filled shapes. You can set properties for the shapes that you draw using the Graphics object, such as foreground color, background color, and alpha.

Code sample: Drawing shapes on the screen

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.container.MainScreen;

import net.rim.device.api.ui.Graphics;

public class DrawingShapesDemo extends UiApplication
{
    public static void main(String[] args)
    {
    	   DrawingShapesDemo theApp = new DrawingShapesDemo();       
        theApp.enterEventDispatcher();
    }
    
    public DrawingShapesDemo()
    {
        pushScreen(new DrawingShapesDemoScreen());
    }    
}

public class DrawingShapesDemoScreen extends MainScreen
{
    public DrawingShapesDemoScreen()
    {            
        setTitle("Drawing Shapes Demo");
    }

//Override paint() of the MainScreen class.    
    protected void paint(Graphics g)
    {

//To draw a colored rectangle: 
//Invoke setColor() to set the color of the rectangle.
//Invoke fillRect() to draw a filled rectangle.
//Invoke drawRect() to draw an empty rectangle.
    	   g.setColor(0x009900);
    	   g.fillRect(10, 10, 80, 80);
    	   g.drawRect(15, 15, 80, 80);
 
//To draw a colored rectangle with rounded corners: invoke 
//setColor() to set the color of the rectangle.
//Invoke fillRoundedRect() to draw a filled rectangle, and invoke 
//drawRoundedRect() to draw an empty rectangle.   	
       	g.setColor(0x6699FF);
        g.fillRoundRect(120, 10, 80, 80, 25, 25);
        g.drawRoundRect(125, 15, 80, 80, 25, 25);

//To draw a colored ellipse: invoke setColor() to set the 
//color of the ellipse.
//Invoke fillEllipse() to draw a filled ellipse, and invoke 
//drawEllipse() to draw an empty ellipse.    	
    	   g.setColor(0xCCCCCC);
    	   g.fillEllipse(100, 200, 160, 240, 100, 270, 0, 360);
    	   g.drawEllipse(105, 205, 165, 245, 105, 275, 0, 360);
    }
}