Graphic and Events
Peter Komisar ©  Conestoga College  version  1.3 /  2009

reference: Learning Wireless Java, Qusay H. Mahmoud,
O'Reilly, User’s Guide Sun JavaTM Wireless Toolkit for
CLDC Version 2.5.2, Sun MicroSystems, 'Java 2ME and
MIDP Development', John Muchow,
The Mobile Information
Device Profile and MIDlets, Part 2, Kim Topley, onjava.com



Graphics

The Graphic class used in the Micro edition is very
robust and supports a similar set of actions as can
be found in the Standard edition plus a set of new
elements.

You don't have the option to cast the Graphics
class to the 2DGraphics class as you do with the
standard edition of Java.

Following are the methods in minimal signature
form without return types and arguments.


Graphics Methods in Minimal Form


clipRect()
copyArea()
drawArc()
drawChar()
drawChars()
drawImage()
drawLine()
drawRect()
drawRegion()
drawRGB()
drawRoundRect()
drawString()
drawSubstring()
fillArc()
fillRect()
fillRoundRect()
fillTriangle()
getBlueComponent()
getClipHeight()

getClipWidth()
getClipX()
getClipY()
getColor()
getDisplayColor()
getFont()
getGrayScale()
getGreenComponent()
getRedComponent()
getStrokeStyle()
getTranslateX()
getTranslateY()
setClip()
setColor()
setColor()
setFont(t)
setGrayScale()
setStrokeStyle()
translate()


Differences Between the Standard and
Micro Edition Graphics


On first glance the two editions look similar but there
are major differences between the Graphics models.
A first difference regards the use of colors.


The Color Model

As in the Standard Edition, the MicroEdition uses
a Red, Green Blue Model which is described as
24 bits, with 8 bits used for color. Eight bits may
also be used to describe an alpha or transparency
value.

Alpha Red Green Blue Bit Mapping

| alpha bits  31 - 24 | red bits  23 - 16 | green bits  15 - 8 | blue bits  7 - 0 |



No Color Class


In the Micro Edition you do not have a Color class
to supply color constants or constructors to build
colors. Instead, in Wireless Java, this stage is by-
passed and the red, green blue values are supplied
directly to the appropriate setColor( ) method.

Following are the forms of the setColor methods
found in the Graphics class.

The setColor( )  Methods

Example

g. setColor( 44,44,44 );


Many methods of the standard edition methods are
not supported. A few examples are shown below.


Examples of Standard Methods Not Supported
// unavailable in both draw and fill


The drawRect( ) and fillRect( ) Methods

The draw and fill rectangle methods are based
on specifying four integers, two for x,y coordinates
and two for width and height.


Signature for the drawRect( ) Method
public void drawRect
(int x, int y, int width, int height)
Following is an example where the coordinate
is (10,10) with respect to the upper left corner,
the width is 50, and the height is 80.


Example

g.drawRect(10,10, 50,80);

Several other methods use the drawRect( ) format
as a basis for creating more complex forms. You
will be familiar with the approach from standard Java.

The approach is to regard the initial rectangle as an
imaginary container for a rounded rectangle, an oval,
eclipse or an arc, where the rounded forms have edges
that touch the imaginary rectangle that frames the form.

You will see this basic form underlying the next methods
that are mentioned, the draw and fillRoundRect( )
methods.


The draw and fillRoundRect( ) Methods


Again we see the MicroEdition is focused on being
economical.  Recognize that the drawRoundRect( )
method and it's fill counterpart can be used to round
corners on squares but also to draw fully round
shapes.

The signature for the draw and fillroundRect(  )
methods is as follows.

The draw and fillRoundRect Signatures

void drawlRoundRect
(int x, int y,
int width, int height,
int arcWidth, int arcHeight)

void fillRoundRect
(int x, int y,
int width, int height,
int arcWidth, int arcHeight)

The first coordinates are the upper left hand corner
coordinates. The next two ints are width and height.
The additional two coordinates describe the width
and height of an imaginary rectangle that contains
an ellipse.


When a Rounded Square Becomes an Oval or Circle

If the ellipse values are the same as the width and
height an oval or a circle is created.


Example


g.drawRoundRect(40,50,40,50,40,50);


The draw and fillArc(  ) Methods

Similarly the draw and fillArc()  methods
may be used to draw or fill a circle. Following
are the method signatures.


The draw and fillArc( ) Methods


The draw and fillArc( ) methods

void drawArc
    (int x, int y,
    int width, int height,
    int startAngle, int arcAngle)

void  fillArc
    (int x, int y,
    int width, int height,
    int startAngle, int arcAngle)


In the case of the arc methods, x and y are the
upper left hand coordinates, width and height
describe an imaginary rectangle and the next two
ints describe a start angle and a degrees of sweep.

Example

g.fillArc( 40,220,130,40,180,180);

// a half circle that could be the bottom of a boat



Drawing Circles with draw and fillArc( )

Similarly the draw and fillArc()  methods may
be used to draw or fill a circle.


Putting the last argument to 360 will complete the
sweep. If the width is the same as the height a
circle is drawn.


Example


 g.fillArc(100,100,30,30,0,360);


The draw and fill Polygon( ) methods can be
replaced with drawString though not as conveniently.


Draw String and Character Methods are Anchored

Another aspect that is different in the Micro edition
is the use of anchor points.  Anchor points will
position text or characters to the four corners of
a specified point. 


drawString( )  and drawChar( ) Methods and Anchor Points

Anchor points minimize computation when placing
text. The method to draw a String of text is defined
below.

Example

public void drawString(String text, int x, int y, int anchor);
The anchor point is represented by the ( x,  y ) coordinate.
The method then draws text relative to that point based
on anchor constants. These are as follows.


Anchor Constants
As with other positioning constants they can be
combined with the OR operator.

Example

TOP |  LEFT

They are defined in the graphics class so you
will see them referenced from the graphics
context reference as in the following example.

Example

g.TOP | g.LEFT

To show the effect of anchors consider the
following code which shows the same character
being printed to the same point but with different
anchoring about that point.

For a reference the code draws an 'X' at the
reference point by drawing two intersecting
lines.

Following is the code that will do this. First
we give the drawLine( ) method a mention.

The drawLine( ) Method

The drawLine( ) method in Java is based on
the 'shortest distance between two points. The
developer supplies the two coordinates and the
system connects them together.

drawLine( ) Signature

void drawLine(int x1, int y1, int x2, int y2)

The following snippet draws a center point
at (60,60) using two lines. The anchors are
then demonstrated with respect to this point.


Anchor Code Snippet


  g.drawLine(59,59,61,61);
  g.drawLine(59,61,61,59);
  g.drawString("O",60,60,g.TOP | g.LEFT);
  g.drawString("O",60,60,g.TOP | g.RIGHT);
  g.drawString("O",60,60,g.BOTTOM | g.LEFT);
  g.drawString("O",60,60,g.BOTTOM | g.RIGHT);


Emulation of Output

O O
 x
O O


There are also drawChar methods and a drawSubString( )
method. Their method signatures are shown below.
These allow drawing a character, a part of an array
of characters or part of a string. These methods, like
drawString make use of anchors.


drawChar( )  and draw


void drawSubstring
(String str, int offset, int len, int x, int y, int anchor)
void  drawChar
(char character, int x, int y, int anchor)
void  drawChars
(char[] data, int offset, int length, int x, int y, int anchor)



General Approaches For Creating Graphics

The intersect point (0,0) refers to the upper left
hand corner.  Calls are made off of the Graphics
object which is provided by the system. 

In the following example a Canvas class is
subclassed and the graphics calls are made in it.
This class is added to a Display in a Midlet class.
The source code for each class was saved separately
in the src directory of a new MIDlet project. Note
though only the MIDlet class is marked public.

Included are the work around described above
for drawing round or oval objects.

Notice the Canvas class has it's paint method
overridden. It is the argument of the paint method
that supplies the Graphics context for doing the
graphics routines.

// both were saved as separate source codes
// with their own imports in the 'src' directory
// of their project


Canvas Class Example

import javax.microedition.lcdui.*;

class Drawing extends Canvas{
 
  public void paint(Graphics g){ 
 
    g.drawLine(59,59,61,61);
    g.drawLine(59,61,61,59);
    g.drawString("O",60,60,g.TOP | g.LEFT);
    g.drawString("O",60,60,g.TOP | g.RIGHT);
    g.drawString("O",60,60,g.BOTTOM | g.LEFT);
    g.drawString("O",60,60,g.BOTTOM | g.RIGHT);

    // draws an oval
    g.setColor(33,111,33);
    g.drawRoundRect(35,40,50,70,50,70);
    // using an int as color value
    // draws the boat bottom
    g.setColor(180999);
    g.fillArc( 40,220,130,40,180,180);

    g.setColor(255,33,55);
    g.fillArc(100,100,30,30,0,360);
    // black outline
    g.setColor(0,0,0);
    g.drawArc(100,100,30,30,0,360);
 
    char[] characters=new char[]{'A','-','B','-','C','-','D' };
    g.drawChars(characters,2,3,170,140, g.TOP | g.RIGHT);

    // the original intent of the round rect method
     g.setColor(10,50,200);
     g.drawRoundRect(140,130,50,90,10,20);
    }
  }


The MIDlet Runner Class

import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;


public class GraphX extends MIDlet{

public void startApp() {
   Display display = Display.getDisplay(this);

   Drawing drawing =new Drawing();
  
 
   display.setCurrent(drawing);
   }
public void destroyApp(boolean unconditional){}
public void pauseApp(){}
}

 Drawing in an Inner Class

For a small graphic an inner class might have
been used but there is really no obvious advantage
to using one except to have the MIDlet and graphics
call all in one source code.

import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class GraphZ extends MIDlet{

public void startApp() {
   Display display = Display.getDisplay(this);
   InnerSelf inner=new InnerSelf();
   display.setCurrent(inner);
   }
public void destroyApp(boolean unconditional){}
public void pauseApp(){}

  class InnerSelf extends Canvas{

   public void paint(Graphics g){
 
     g.setColor(0,50,100);    
     g.fillTriangle(100,100,150,100,75,50);

     g.setColor(255,33,77);
     g.fillTriangle(100,100,100,150,125,125);

      g.setColor(55,233,10);
     g.fillTriangle(100,100,50,50,60,90);
     }
   }
}




More Graphics Methods

The drawTriangle( )  Method

A great many complex shapes can be created
using triangles  The method is easy to use
calling for three points to be specified as ints.
There is no drawTriangle( ), presumably because
you can create a triangle outline with drawLine( ).

The fillTriangle( ) method Signature

void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3)


Following is an example.

Triangle Example

import javax.microedition.lcdui.*;

class Drawing2 extends Canvas{
  
    public void paint(Graphics g){
  
     g.setColor(0,50,100);     
     g.fillTriangle(100,100,150,100,75,50);

     g.setColor(255,33,77);
     g.fillTriangle(100,100,100,150,125,125);

      g.setColor(55,233,10);
     g.fillTriangle(100,100,50,50,60,90);
     }
  
}


The translate( )  Method

The translate method changes the system
reference point. For instance, assuming your
screen is 240 by 320, you could translate
using the translate( ) method as follows.

Example

g.translate(120,160)

This makes the center of the screen act effectively
like (0,0).


The translate( ) Method Signature

void translate( int x, int y)


Sample Code


 import javax.microedition.lcdui.*;

class Drawing3 extends Canvas{
  public void paint(Graphics g){
     g.translate(120,160);
     g.drawLine(-5,-5,5,5);
     g.drawLine( 5,-5,-5,5);
     }
  }

// draws an x at the center of the screen
// offsetting the default setting


Events


In this note we do a quick overview of the Event
model used in the Micro Edition. Next week we
go into detail.

There are similarities in the Event Model used
in the Micro Edition to that of the Standard Edition,
namely the definition of listener interfaces.

Also similar to the standard model is the
implementation of ItemStateListener. It works
more or less the same as the model used in
standard Java.

On the other hand, the Micro Edition uses a
Command class in a unique way. The details
regarding implementing this class are quite
different so the developer may as well treat the
processing of events in the Micro edition, at
least with respect to the Command class as a
new architecture.


Technical Details

In the Micro Edition calls to action methods are
serialized or called in order in a single thread of
execution. Additionally the MIDP thread model is
'thread safe' and includes a mechanism for event
synchronization.


High and Low Level Events


In the Micro Edition there are two sorts of events
described. High level events are those created by
working with high level components, such as
clicking an item on a list. (These are similar to
semantic events that are described in the standard
event model.) Low level events come from keyboard
clicks or other input devices.

// high level or 'semantic' events are composed of
// low level
event processing calls



Command Class


Much of the event model in Wireless Java is based
on a Command class which has the following single
constructor.

Command Class Constructor

public Command(String label, int commandType, int priority)

The constructor takes the following three arguments.


Command Constructor Arguments

The Command class supplies the following methods
for getting Command argument information.


Methods for returning Argument Information


Displayable Command Methods


Displayable defines the following command methods
which are inherited by Screen and Canvas.


Displayable Command Methods
The commands allow binding commands to objects
that inherit from Displayable.

The following code uses the Command constructor
and the addCommand( ) method to set up a menu
box with these commands associated. No action
processing has been coded in yet.


Action Code Sample
// no action processing yet

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

//This doesn't do much note a menu has been added
// with associated labels. No actions have been
// associated yet



public class Actions extends MIDlet{

public void startApp() {
   Display display = Display.getDisplay(this);
TextBox tb = new TextBox("The Store",
"Welcome to the Store",40,TextField.ANY);
Command exit = new Command("Exit",Command.SCREEN,1);
Command products=new Command("Products",Command.SCREEN,2);
Command add2Cart=new Command("Add to Cart",Command.SCREEN,2);
tb.addCommand(exit);
tb.addCommand(products);
tb.addCommand(add2Cart);
 
   display.setCurrent(tb);
   }
public void destroyApp(boolean unconditional){}
public void pauseApp(){}

}


Event Interfaces

User activated events are invoked via 'callback methods'.
Qusay Mahmoud offers the following definition for a callback
in his book 'Learning Wireless Java'.

"Callbacks are actually invocations of programmer-
defined methods performed by the underlying
application in response to actions taken by a user
at runtime."  - 
Qusay Mahmoud

Four kinds of callbacks are described in MIDP.

The methods spoken of here are defined inside
interfaces that the developer needs to provide
implementations for.

Following are the three Event Listener interfaces
all defined inside the javax.microedition.lcdui
package.

The first two of these event interfaces are used
in a similar fashion which is unique to the Micro
edition while the last of these, ItemStateListener
is used more like the model that is defined for the
Java standard edition.


Micro Event Interfaces
// the other lcdui interface is Choice but it isn't an event interface


The CommandListener Interface


The CommandListener Interface defines the
following method.


CommandListener Interface Method

public void  commandAction
                     (Command c, Displayable d)


// a command event has occurred on Displayable d


Listeners


Listeners are classes that implement the Listener
intefaces. Both Screen and Canvas can have listeners
for command events.

Registration

The listener has to be registered with the source
of the event. This is done with a registration method.
In the Micro edition a set method( ) is used.


Registration Method for CommandListeners

public void setCommandListener
                               (CommandListener cl)


A First Action Example

How the following code work may not be as
you first envisioned. The list supplies a set of
choices. The action processing though happens
via the pop-up menu that is activated separately.

Adding two or more CommandActions of Screen
type will result in a menu being created for those
items. It is from this menu that you see the actions
processed.

We tied the actions to the choices on the list
using the following list methods in combination.
One gets the string associated with the item
based on the index that is selected.

Example

list.getString(list.getSelectedIndex())

A command of Exit type will activate the left upper
button to trigger the MIDlets exit.

Calling and Overriding destroyApp( ) will give
some teeth to this action. Comment the destroyApp( )
method after first running it and then compile and
run the MIDlet again.

Today's example causes a print to console. Later
we will send output back into our display. 


CommandListener Code Example

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class Actions2 extends MIDlet implements CommandListener{
    List list;
   Display display;

static final Command infoCommand
     = new Command("Information",Command.ITEM,2);

static final Command buyCommand
     = new Command("Add To Cart",Command.ITEM,2);

static final Command exitCommand
     = new Command("Exit",Command.STOP,2);

public void startApp() {
     display = Display.getDisplay(this);
     list = new List("Vehicles",Choice.EXCLUSIVE);
     list.append("Gas", null);
     list.append("Diesel", null);
     list.append("Electric", null);
     list.append("Hybrid", null);
     list.append("(***Items are not activated!****)",null);

 
  list.addCommand(exitCommand);
  list.addCommand(buyCommand);
  list.addCommand(infoCommand);
  list.setCommandListener(this);
  display.setCurrent(list);
  }

// action method
public void  commandAction(Command c, Displayable d){

String label=c.getLabel();
if(label.equals("Exit")){
   System.out.println("Exit Activated!");
 //  destroyApp(true);
   }

if(label.equals("Information"))
   System.out.println("Get the Information Page!\n" +
    "Vehicle Type: " + list.getString(list.getSelectedIndex()));

if(label.equals("Add To Cart"))
   System.out.println("Get the Buy Page!\n" +
     "Vehicle Type: " + list.getString(list.getSelectedIndex()));
   }


public void destroyApp(boolean unconditional){
 notifyDestroyed();}

public void pauseApp(){}
}



Assignment


Put all the following in a single Midlet.

1 )  Between each of the following elements,
change the color of the component being drawn.

2 ) Use the drawTriangle( )  method to draw a
five pointed star. 

3) Again use the drawTriangle method to draw
a diamond in the center of the star.

4) Create a rectangle with rounded corners that
contains the star.

5) Set  some text into the display using drawString( )
or drawChar( ).

Screenshot the output and submit code.

// We will tie the above event coverage into the next assignment