tcs0363 mobile programming using j2me chapter 6 lists and ... · tcs0363 mobile programming using...
TRANSCRIPT
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Handling User CommandsNone of the UI elements so far have allowed any
interaction from the user! A MIDlet interacts with a
user through commands. A command is the
equivalent of a button or a menu item in a normal
application, and can only be associated with a
displayable UI element. Like a ticker, the
Displayable class allows the user to attach a
command to it by using the method
addCommand(Command command). Unlike a ticker,
a displayable UI element can have multiple
commands associated with it.1
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The Command class holds the information about a
command. This information is encapsulated in four
properties. These properties are: a short label, an
optional long label, a command type, and a priority.
You create a command by providing these values in
its constructor:
Command exitCommand = new Command("EXIT",
Command.EXIT, 1);
Note that commands are immutable once created.
2
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
By specifying the type of a command, you can let the
device running the MIDlet map any predefined keys
on the device to the command itself. For example, a
command with the type OK will be mapped to the
device's OK key. The rest of the types are: BACK,
CANCEL, EXIT, HELP, ITEM, SCREEN, and
STOP. The SCREEN type relates to an application-
defined command for the current screen. Both
SCREEN and ITEM will probably never have any
device-mapped keys.
3
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
By specifying a priority, you tell the AMS running the
MIDlet where and how to show the command. A lower
value for the priority is of higher importance, and
therefore indicates a command that the user should be
able to invoke directly. For example, you would
probably always have an exit command visible to the
user and give it a priority of 1. Since the screen space is
limited, the device then bundles less-important
commands into a menu. The actual implementation
varies from device to device, but the most likely
scenario involves one priority-1 command displayed
along with an option to see the other commands via a
menu. Figure 7 shows this likely scenario.4
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
5
Figure 7. The way commands are displayed. The menu
pops up when the user presses the key corresponding to
the menu command.
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The responsibility for acting on commands is
performed by a class implementing the
CommandListener interface, which has a single
method: commandAction(Command com,
Displayable dis). However, before command
information can travel to a listener, The listener is
registered with the method
setCommandListener(CommandListener listener)
from the Displayable class.
Putting this all together, Listing 6 shows how to add
some commands to the form discussed in Listing 4.6
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
package com.j2me.part2;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.Spacer;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.DateField;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Command;
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.CommandListener;
7
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
public class FormExample
extends MIDlet
implements CommandListener {
private Form form;
private Gauge gauge;
private Spacer spacer;
private ImageItem imageItem;
private TextField txtField;
private DateField dateField;
private StringItem stringItem;
private ChoiceGroup choiceGroup;
public FormExample() {
form = new Form("Your Details");
// a StringItem is not editable
stringItem = new StringItem("Your Id: ", "WXP-890");
form.append(stringItem);
// you can accept Date, Time or DateTime formats
dateField =
new DateField("Your DOB: ", DateField.DATE);
form.append(dateField);
8
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
// similar to using a TextBox
txtField = new TextField(
"Your Name: ", "", 50, TextField.ANY);
form.append(txtField);
// similar to using a List
choiceGroup = new ChoiceGroup(
"Your meals: ",
Choice.EXCLUSIVE,
new String[] {"Veg", "Non-Veg"},
null);
form.append(choiceGroup);
// put some space between the items
spacer = new Spacer(20, 20);
form.append(spacer);
// a gauge is used to show progress
gauge = new Gauge("Step 1 of 3", false, 3, 1);
form.append(gauge);
9
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
// an image may not be found,
// therefore the Exception must be handled
// or ignored
try {
imageItem = new ImageItem(
"Developed By: ",
Image.createImage("/duke.gif"),
ImageItem.LAYOUT_DEFAULT,
"Duke");
form.append(imageItem);
} catch(Exception e) {}
// create some commands and add them
// to this form
form.addCommand(
new Command("EXIT", Command.EXIT, 2));
form.addCommand(
new Command("HELP", Command.HELP, 2));
form.addCommand(
new Command("OK", Command.OK, 1));
// set itself as the command listener
form.setCommandListener(this);
}
10
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
// handle commands
public void commandAction(
Command com, Displayable dis) {
String label = com.getLabel();
if("EXIT".equals(label))
notifyDestroyed();
else if("HELP"Equals(label))
displayHelp();
else if("OK"Equals(label))
processForm();
}
public void displayHelp() {
// show help
}
public void processForm() {
// process Form
}
11
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
public void startApp() {
Display display = Display.getDisplay(this);
display.setCurrent(form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
Listing 6. Adding commands to a form
12
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The differences from Listing 4 are highlighted
in bold. The command listener in this case is
the form class itself, and therefore, it
implements the commandAction() method.
Note that this method also accepts a
displayable parameter, which is very useful.
Because commands are immutable, they can
be attached to multiple displayable objects,
and this parameter can help distinguish which
displayable object invoked the command.
13
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Working with the Low-Level APIThe low-level API for MIDlets is composed of the Canvas
and Graphics classes (we will discuss the GameCanvas class
in the next article). The Canvas class is abstract; you must
create your own canvases to write/draw on by extending this
class and providing an implementation for the
paint(Graphics g) method, in which the actual drawing on a
device is done. The Canvas and Graphics classes work
together to provide low-level control over a device.
Let's start with a simple canvas. Listing 7 shows an example
canvas that draws a black square in the middle of the device
screen.14
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
package com.j2me.part2;
import javax.microedition.lcdui.Canvas;
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
public class CanvasExample
extends MIDlet {
Canvas myCanvas;
public CanvasExample() {
myCanvas = new MyCanvas();
}
public void startApp() {
Display display = Display.getDisplay(this);
// remember, Canvas is a Displayable so it can
// be set on the display like Screen elements
display.setCurrent(myCanvas);
// force repaint of the canvas
myCanvas.repaint();
}
15
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
class MyCanvas extends Canvas {
public void paint(Graphics g) {
// create a 20x20 black square in the center
g.setColor(0x000000); // make sure it is black
g.fillRect(
getWidth()/2 - 10,
getHeight()/2 - 10,
20, 20);
}
}
Listing 7. Creating and displaying a Canvas
16
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The class MyCanvas extends Canvas and overrides the paint()
method. Although this method is called as soon as the canvas is made
the current displayable element (by setCurrent(myCanvas)), it is a
good idea to call the repaint() method on this canvas soon afterwards.
The paint() method accepts a Graphics object, which provides
methods for drawing 2D objects on the device screen. For example,
in Listing 7, a black square is created in the middle of the screen
using this Graphics object. Notice that before drawing the square,
using the fillRect() method, the current color of the Graphics object
is set to black by using the method g.setColor(). This is not
necessary, as the default color is black, but this illustrates how to
change it if you wanted to do so.
If you run this listing, the output on the emulator will be as shown in
Figure 8.
17
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
18
Figure 8. Drawing a single square in the middle of a Canvas
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Notice the highlighted portion at the top in
Figure 8. Even though the MIDlet is running,
the AMS still displays the previous screen.
This is because in the paint() method, the
previous screen was not cleared away, and the
square was drawn on the existing surface. To
clear the screen, you can add the following
code in the paint() method, before the square
is drawn.
19
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
g.setColor(0xffffff);
// sets the drawing color to white
g.fillRect(0, 0, getWidth(), getHeight());
// creates a fill rect which is the size of the screen
20
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Note that the getWidth() and getHeight() methods return the size
of the display screen as the initial canvas, which is the whole
display screen. Although the size of this canvas cannot be
changed, you can change the size and location of the clip area in
which the actual rendering operations are done. A clip area, in
Graphics, is the area on which the drawing operations are
conducted. The Graphics class provides the method setClip(int
x, int y, int width, int height) to change this clip area, which in
an initial canvas is the whole screen, with the top left corner as
the origin (0, 0). Thus, if you use the method getClipWidth() (or
getClipHeight()) on the Graphics object passed to the paint
method in Listing 7, it returns a value equal to the value returned
by the getWidth() (or getHeight()) method of the Canvas.
21
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The Graphics object can be used to render not only squares
and rectangles, but arcs, lines, characters, images, and text, as
well. For example, to draw the text "Hello World" on top of
the square in Listing 7, you can add the following code before
or after the square is drawn:
g.drawString("Hello World", getWidth()/2, getHeight()/2 - 10,
Graphics.HCENTER | Graphics.BASELINE);
This will result in the screen shown in Figure 9.
22
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
23
Figure 9. Drawing text using the Graphics object
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Text, characters, and images are positioned using the
concept of anchor points. The full syntax of the
drawString() method is drawstring(String text, int x, int y,
int anchor). The anchor positioning around the x, y
coordinates is specified by bitwise ORing of two constants.
One constant specifies the horizontal space (LEFT,
HCENTER, RIGHT) and the other specifies the vertical
space (TOP, BASELINE, BOTTOM).
24
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Thus, to draw the "Hello World" text on top of the
square, the anchor's horizontal space needs to be
centered around the middle of the canvas
(getWidth()/2) and hence, I have used the
Graphics.HCENTER constant. Similarly, the vertical
space is specified by using the BASELINE constant
around the top of the square (getHeight()/2 - 10).
You can also use the special value of 0 for the
anchor, which is equivalent to TOP | LEFT.
25
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Images are similarly drawn and positioned on the
screen. You can create off-screen images by using
the static createImage(int width, int height) method
of the Image class. You can get a Graphics object
associated with this image by using the
getGraphics() method. This method can only be
called on images that are mutable. An image loaded
from the file system, or over the network, is
considered an immutable image, and any attempt to
get a Graphics object on such an image will result in
an IllegalStateException at runtime.
26
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Using anchor points with images is similar to using
them with text and characters. Images allow an
additional constant for the vertical space, specified
by Graphics.VCENTER. Also, since there is no
concept of a baseline for an image, using the
BASELINE constant will throw an exception if used
with an image.
Listing 8 shows the code snippet from the MyCanvas
class paint() method that creates an off-screen image,
modifies it by adding an image loaded from the file
system, and draws a red line across it. Note that you
will need the image duke.gif in the res folder of the
CanvasExample MIDlet.27
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
// draw a modified image
try {
// create an off screen image
Image offImg = Image.createImage(25, 19);
// get its graphics object and set its
// drawing color to red
Graphics offGrap = offImg.getGraphics();
offGrap.setColor(0xff0000);
// load an image from file system
Image dukeImg =
Image.createImage("/duke.gif");
// draw the loaded image on the off screen
// image
offGrap.drawImage(dukeImg, 0, 0, 0);
// and modify it by drawing a line across it
offGrap.drawLine(0, 0, 25, 19);
28
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
// finally, draw this modified off screen
// image on the main graphics screen
// so that it is just under the square
g.drawImage(
offImg, getWidth()/2,
getHeight()/2 + 10,
Graphics.HCENTER | Graphics.TOP);
} catch(Exception e) { e.printStackTrace(); }
29
Listing 8. Creating, modifying, and displaying an off-
screen image on a Canvas
The resultant screen, when combined with the "Hello
World" text drawn earlier, will look like Figure 10.
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
30
Figure 10. Text, a square, and a
modified image drawn on a Canvas
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The Canvas class provides methods to interact
with the user, including predefined game
actions, key events, and, if a pointing device
is present, pointer events. You can even attach
high-level commands to a canvas, similar to
attaching commands on a high-level UI
element.
31
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Each Canvas class automatically receives key events
through the invocation of the keyPressed(int
keyCode), keyReleased(int keyCode), and
keyRepeated(int keyCode). The default
implementations of these methods are empty, but not
abstract, which allows you to only override the
methods that you are interested in. Similar to the key
events, if a pointing device is present, pointer events
are sent to the pointerDragged(int x, int y),
pointerPressed(int x, int y), and pointerReleased(int
x, int y) methods.32
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
The Canvas class defines constants for key codes
that are guaranteed to be present in all wireless
devices. These key codes define all of the numbers
(for example, KEY_NUM0, KEY_NUM1,
KEY_NUM2, and so on) and the star (*) and pound
(#) keys (KEY_STAR and KEY_POUND). This
class makes it even easier to capture gaming events
by defining some basic gaming constants. There are
nine constants that are relevant to most games: UP,
DOWN, LEFT, RIGHT, FIRE, GAME_A,
GAME_B, GAME_C, and GAME_D. But how does
a key event translate to a gaming event?
.
33
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
By the use of the getGameAction() method. Some devices
provide a navigation control for moving around the screen,
while some devices use the number keys 2, 4, 6, and 8. To
find out which game action key was pressed, the Canvas
class encapsulates this information and provides it in the
form of the game actions. All you, as a developer, need to
do is to grab the key code pressed by the user in the right
method, and use the getGameAction(int keyCode) method
to determine if the key pressed corresponds to a game
action. As you can guess, several key codes can correspond
to one game action, but a single key code may map to, at
most, a single game action.
34
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Listing 9 extends the original code from Listing 7 to
add key code handling. In this listing, the square in
the middle of the screen is moved around with the
help of the navigation buttons
35
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
package com.j2me.part2;
import javax.microedition.lcdui.Canvas;
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
public class CanvasExample
extends MIDlet {
Canvas myCanvas;
public CanvasExample() {
myCanvas = new MyCanvas();
}
public void startApp() {
Display display = Display.getDisplay(this);
// remember, Canvas is a Displayable so it can
// be set on the display like Screen elements
display.setCurrent(myCanvas);
// force repaint of the canvas
myCanvas.repaint();
}
36
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
class MyCanvas extends Canvas {
public void paint(Graphics g) {
// create a 20x20 black square in the center
// clear the screen first
g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x000000); // make sure it is black
// draw the square, changed to rely on instance variables
g.fillRect(x, y, 20, 20);
}
37
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
public void keyPressed(int keyCode) {
// what game action does this key map to?
int gameAction = getGameAction(keyCode);
if(gameAction == RIGHT) {
x += dx;
} else if(gameAction == LEFT) {
x -= dx;
} else if(gameAction == UP) {
y -= dy;
} else if(gameAction == DOWN) {
y += dy;
}
// make sure to repaint
repaint();
}
// starting coordinates
private int x = getWidth()/2 - 10;
private int y = getHeight()/2 - 10;
// distance to move
private int dx = 2;
private int dy = 2;
}
38
Listing 9. Handling key events to
move the square
TCS0363 Mobile Programming Using J2ME
Lists and Forms
Management and Science University
Chapter 6
Week 9
Notice that in this listing, the code to paint the
square has been modified to rely upon instance
variables. The keyPressed() method has been
overridden and therefore, whenever the user presses
a key, this method is invoked. The code checks if
the key pressed was a game key, and based on
which game key was pressed, changes the
coordinates of the square accordingly. Finally, the
call to repaint() in turn calls the paint() method,
which moves the square on the screen as per the
new coordinates.39