Java Programming Notes # 2588
- Preface
- General background information
- Preview
- Discussion and sample code
- Run the programs
- Summary
- What’s next?
- Resources
- Complete program listings
- Copyright
- About the author
Preface
This is Part 1 of a two-part lesson in a series of tutorial lessons designed to teach you how to write programs using the Sun Java Wireless Toolkit for CLDC. The first lesson was titled Getting Started with MIDlets and the Sun Java Wireless Toolkit for CLDC. The previous lesson was titled Programming MIDlets for Interactive Behavior (see Resources).
What you will learn
In this lesson, you will learn how to use several methods of the Canvas class (including paint and repaint), along with several methods of the Graphics class to draw text and lines on the cell phone screen. You will learn how to use anchor point coordinates to control the position of text that is drawn on the screen. You will also learn how to handle keyPressed events fired by a Canvas object.
Viewing tip
I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.
Figures
- Figure 1. Partial class hierarchy for MIDP 2.0.
- Figure 2. Output from MIDlet named Canvas01 in Sun emulator.
- Figure 3. Sun cell phone emulator output for the MIDlet named Canvas02.
Listings
- Listing 1. The main class for the MIDlet named Canvas01.
- Listing 2. Beginning of the member class named MyCanvas.
- Listing 3. Draw eight lines and eight text strings.
- Listing 4. Draw two more lines.
- Listing 5. Beginning of the class for the MIDlet named Canvas02.
- Listing 6. Remainder of the main class for the MIDlet named Canvas02.
- Listing 7. Beginning of the member class named MyCanvas.
- Listing 8. Beginning of the overridden paint method.
- Listing 9. Remainder of the overridden paint method.
- Listing 10. Overridden keyPressed method.
- Listing 11. Source code for the MIDlet named Canvas01.
- Listing 12. Source code for the MIDlet named Canvas02.
Supplementary material
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find a consolidated index at www.DickBaldwin.com.
General background information
If you are familiar with graphics programming in J2SE without the benefit of Java 2D and Java 3D, you will probably be reasonably comfortable with the material in this lesson. J2ME graphics is very similar to graphics programming in the early days of Java, but with some interesting new wrinkles.
Partial class hierarchy for MIDP 2.0
A partial class hierarchy for MIDP 2.0 is shown in Figure 1. Figure 1 includes all of the classes that are included in the package named javax.microedition.lcdui. In addition, Figure 1 includes three classes that are in other packages.
Figure 1. Partial class hierarchy for MIDP 2.0.
|
Classes to be illustrated
I have discussed and illustrated the classes shown in boldface Italics (plus the Choice interface, the CommandListener interface, and the ItemCommandListener interface) in earlier lessons (see Resources). I will discuss and illustrate the following classes in this lesson:
- Canvas class
- Graphics class
- Font class
I will discuss and illustrate the GameCanvas class in a future lesson. I will leave CustomItem as an exercise for the student.
The Canvas class
Here is part of what Sun has to say about the Canvas class:
“The Canvas class is a base class for writing applications that need to handle low-level events and to issue graphics calls for drawing to the display. Game applications will likely make heavy use of the Canvas class. From an application development perspective, the Canvas class is interchangeable with standard Screen classes, so an application may mix and match Canvas with high-level screens as needed. For example, a List screen may be used to select the track for a racing game, and a Canvas subclass would implement the actual game.”
The use of the Canvas class and the GameCanvas class for programming games will be the topic of a future lesson. In this lesson, I will concentrate on using the Canvas class for presenting graphic information on the cell phone screen, and handling key events that are fired by a Canvas object.
Yes, I really did mean key events
Unlike the commands that we studied in an earlier lesson, the Canvas class provides the ability to detect and handle key events in a manner that is very similar, but not identical to the JavaBeans or Delegation event model in J2SE (see Resources).
Pointer events
The Canvas class also provides the ability to detect and handle pointer (mouse like) events on hardware implementations that support them. However, in these lessons, I am constrained to the use of the Sun cell phone emulator, which does not appear to support pointer events. (If it does support pointer events, I haven’t figured out how to make it do so.) Therefore, I will have very little, if anything, to say about pointer events.
Canvas also supports commands
Just like other Displayable objects, Canvas objects also support commands such as EXIT, BACK, OK, etc. (see Programming MIDlets for Interactive Behavior in Resources). Therefore, you can mix command programming and real event-driven programming for Canvas objects.
Canvas is an abstract class
The Canvas class is abstract, so you must extend it in order to use it. The reason for this is that the primary use of the Canvas class is to serve as a surface on which to draw. In order to draw, you must override the paint method of the Canvas class. The only way to override a method is to extend the class to which the method belongs.
Comparison with J2SE
When programming in J2SE (using the JavaBeans source-listener event model), if you want to detect and handle key events on an object that is the source of events, you must:
- Define a class that implements the KeyListener interface.
- Instantiate an object of that class.
- Register the listener object on the source object.
Event handler methods, such as keyPressed are declared in the KeyListener interface and must be defined in your new class. That is not the case with MIDP 2.0. The Canvas class already defines the following empty event-handler methods:
- keyPressed
- keyReleased
- keyRepeated
- pointerDragged
- pointerPressed
- pointerReleased
Handling an event
To handle one of the events in the above list, you must override the corresponding method in your subclass of the Canvas class, writing the desired behavior into your overridden method. If you don’t want to handle any of the events in the above list, just forget about the ones that you don’t want to handle. Unlike the JavaBeans event model, it is not necessary to define empty methods for the events that you don’t want to handle.
More information from Sun
According to Sun,
“Applications receive keystroke events in which the individual keys are named within a space of key codes. Every key for which events are reported to MIDP applications is assigned a key code. The key code values are unique for each hardware key unless two keys are obvious synonyms for each other.”
Sun goes on to tell us,
“MIDP defines the following key codes: KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8, KEY_NUM9, KEY_STAR, and KEY_POUND. (These key codes correspond to keys on a ITU-T standard telephone keypad.)”
Public static final variables
The Canvas class provides a public static final variable (constant) for each of the key codes listed above. Finally, Sun tells us,
“Other keys may be present on the keyboard, and they will generally have key codes distinct from those list above. In order to guarantee portability, applications should use only the standard key codes.”
Did not adhere to the rule
As you will see later, I did not adhere to this rule in one of the sample MIDlets. I wasn’t interested in achieving portability. Rather, I was mainly interested in clarity and I found it easier to be clear using the following key names (which may be peculiar to the Sun emulator) in the MIDlet:
- LEFT
- RIGHT
- UP
- DOWN
- SELECT
These names apply to the arrow keys and the large key in the middle of the arrow keys on the Sun cell phone emulator keypad (see Figure 2).; As mentioned above, they may not apply to similar keys in other cell phone emulators or in real cell phones for that matter. (There is a better way to deal with the arrow keys, which you will learn about in a future lesson on the GameCanvas class.)
Normal versus full-screen mode
Here is some of what Sun has to say on this topic:
“A Canvas can be in normal mode or in full-screen mode. In normal mode, space on the display may be occupied by command labels, a title, and a ticker. By setting a Canvas into full-screen mode, the application is requesting that the Canvas occupy as much of the display space as is possible. In full-screen mode, the title and ticker are not displayed even if they are present on the Canvas, and Commands may be presented using some alternative means (such as through a pop-up menu).”
A Canvas object is in normal mode by default. You will see an example of normal and full-screen modes in one of the sample MIDlets in this lesson.
Numerous methods are defined in the Canvas class. I will illustrate the use of many of those methods in the sample MIDlets in this lesson.
The Graphics class
Sun describes this class as follows:
“Provides simple 2D geometric rendering capability.”
While true, this statement hardly does justice to the importance of the Graphics class.
No public constructor
The Graphics class doesn’t have a public constructor, so you can’t directly instantiate an object of the Graphics class. I am aware of at least two ways to get access to an object of the class.
The overridden paint method
The paint method that I mentioned earlier is a callback method. Whenever your Canvas object is visible on the screen and the system needs to display graphics information on that canvas, it will call your overridden paint method. When your overridden paint method is called, it will receive a reference to an object of Graphics class.
You can think of that object as a drawing surface that represents the screen. When you call the various methods of the Graphics class to draw pictures on the Graphics object, those pictures will appear on the screen (assuming that your MIDlet currently has access to the screen).
The createImage and getGraphics methods
As you will see in one the sample MIDlets in this lesson, you can use the createImage and getGraphics methods together to get access to an off-screen drawing area that is represented by a Graphics object. When you use the various methods of the Graphics class to draw on that Graphics object, the results are not immediately visible. Rather, you are simply drawing in memory when you do that and only you know what is happening.
This makes it possible for you to compose a complex drawing in memory and then transfer it to the Canvas object (the screen) very quickly by calling the drawImage method on the Canvas passing the off-screen image’s reference as a parameter. This is often a more visually pleasing approach than composing a complex drawing on the screen in full view of the user, particularly if the time required to compose the drawing is significant.
|
Drawing primitives
The methods of the Graphics class provide drawing primitives for text, images, lines, rectangles, and arcs. Rectangles and arcs may be filled with a solid color. Rectangles may also be specified with rounded corners.
The coordinate system
The origin of the default coordinate system is at the upper left-hand corner of the screen or off-screen drawing area. The X-axis direction is positive towards the right, and the Y-axis direction is positive downwards. You can translate the origin to some other location if you want to by calling the translate method.
For example, by using the translate method and the appropriate arithmetic operations, you could cause the origin to be relocated to the center of the screen with the positive Y-axis direction going up the screen instead of down.
You can assume that horizontal and vertical distances in the coordinate system represent equal distances on the actual device display. In other words, if you draw a square, it won’t be turned into a rectangle and if you draw a circle, it won’t be turned into an ellipse.
All coordinates are specified as integers.
Drawing text
When a character is painted, the pixels forming the character’s shape are filled with the Graphics object’s current color. The pixels that are not part of the character’s shape are left untouched. Several methods are available to draw text. As far as I know, you can only draw text horizontally.
Line stroke styles
Lines, arcs, rectangles, and rounded rectangles may be drawn with either a SOLID or a DOTTED stroke style. The default is SOLID. You can change the style by calling the setStrokeStyle method, which doesn’t affect fill, text, and image operations.
Lines, arcs, rectangles, and rounded rectangles are drawn with a stroke that is one pixel wide. If you need additional width, you must draw two or more lines in parallel.
Clipping
Sun tells us,
“The clip is the set of pixels in the destination of the Graphics object that may be modified by graphics rendering operations.”
To make a long story short, there is a single clip per Graphics object, and it is a rectangle that you can set with a call to the setClip method. The only pixels modified by graphics operations are those that lie within the clip rectangle. Pixels outside the clip rectangle are not modified by any graphics operations.
Anchor points
One of the more complex aspects of the MIDP 2.0 graphics drawing system is the concept of anchor points. Anchor points apply when you are drawing text, images, regions, and areas. (They do not apply when drawing lines, arcs, rectangles, and rounded rectangles.)
Later, I will present and explain a sample MIDlet named Canvas01 that illustrates what is meant by anchor points in conjunction with the drawing of text. (The interpretation is generally the same when drawing images, etc.) The output from the MIDlet, when run in the Sun cell phone emulator, is shown in Figure 2. I will explain the output from the MIDlet here, and explain the code that produced that output later.
Figure 2. Output from MIDlet named Canvas01 in Sun emulator.
|
Drawing parameters
When you call the drawString method to draw text on the screen, you must provide the following four parameters:
- String string – the text string to be drawn.
- int x – a horizontal coordinate value.
- int y – a vertical coordinate value.
- int anchor – an anchor point value.
The big question…
The parameter values x and y clearly specify a point in the Cartesian coordinate system. The big question is what does the location of that point in the coordinate system have to do with the location of the text (or the image, etc.)?
Allowable anchor-point values
The allowable anchor-point values are given below in terms of public static final variables (constants) of the Graphics class:
The key on the left with the picture of the house also doesn’t fire a keyPressed event.
The key pressed order
Figure 3 shows the result of starting at the top left soft key and pressing keys going from left to right, top to bottom, excluding the two keys mentioned above. The names of most of the keys in the Sun emulator are pretty easy to correlate with the label on the key. Two that may not be clear are SELECT and CLEAR. The SELECT key is the large square key in the middle of the arrow keys. The CLEAR key is the key on the right with the picture of the audio speaker.
Comparing full-screen and normal mode
You can see one of the differences between full-screen mode and normal mode by comparing Figure 3, (which is in full-screen mode) and Figure 2, (which is in normal mode). Since neither of these MIDlets displays a title and a ticker, the main difference between Figure 2 and Figure 3 is the disappearance of the gray bar at the bottom of the screen in Figure 3 where soft key commands normally appear. (I will have more to say about this later.)
Beginning of the class for the MIDlet named Canvas02
Listing 5 shows the beginning of the class for the MIDlet named Canvas02 including the constructor.
Listing 5. Beginning of the class for the MIDlet named Canvas02.
public class Canvas02 extends MIDlet{ Canvas myCanvas; public Canvas02(){//Constructor System.out.println("Construct MIDlet"); myCanvas = this.new MyCanvas(); //Guarentee that the screen gets painted. myCanvas.repaint(); //Add three commands to the Canvas myCanvas.addCommand(new Command("EXIT", Command.EXIT,2)); myCanvas.addCommand(new Command("BACK", Command.BACK,2)); myCanvas.addCommand(new Command("OK",Command.OK,2)); }//end constructor |
Three commands are added
Note that the constructor in Listing 5 adds three commands to the Canvas object. However, even if visible, the commands could not be activated because there is no CommandListener registered on the Canvas object. The commands were added to the Canvas solely to demonstrate the impact of full-screen mode versus normal mode. As mentioned earlier, when the Canvas object is set to full-screen mode, as is the case for this MIDlet, the commands are not visible.
|
Accessing the commands
If the Canvas is switched to normal mode, the commands are displayed on the gray bar that normally appears at the bottom of the screen and also in a command menu accessible from the gray bar. You can demonstrate this behavior by modifying the code to pass true or false to the setFullScreenMode method in the MyCanvas constructor that I will discuss later.
Remainder of the main class for the MIDlet named Canvas02
Listing 6 shows the remainder of the main class for the MIDlet named Canvas02.
Listing 6. Remainder of the main class for the MIDlet named Canvas02.
public void startApp(){ //Make the Canvas the current display. Display.getDisplay(this).setCurrent(myCanvas); }//end startApp public void pauseApp(){ }//end pauseApp public void destroyApp(boolean unconditional){ System.out.println("Destroy MIDlet"); notifyDestroyed(); }//end destroyApp |
There is nothing new in this code so further explanation should not be necessary.
Beginning of the member class named MyCanvas
Listing 7 shows the beginning of the member class named MyCanvas, including the constructor.
Listing 7. Beginning of the member class named MyCanvas.
class MyCanvas extends Canvas{ Vector vect = new Vector(); MyCanvas(){//constructor this.setFullScreenMode(true); }//end constructor |
The constructor calls the method named setFullScreenMode to cause the Canvas to appear on the screen in full-screen mode. If you change the parameter from true to false, the Canvas will revert to normal mode. If what you need is normal mode, you don’t need to call this method because the Canvas is in normal mode by default.
Beginning of the overridden paint method
Listing 8 shows the beginning of the overridden paint method. The method begins by painting the screen white and then setting the drawing color to black. Following this, the method declares some working variables and initializes some of them.
Listing 8. Beginning of the overridden paint method.
public void paint(Graphics g){ //Paint the entire screen white. g.setColor(0xffffff); g.fillRect(0,0,getWidth(),getHeight()); g.setColor(0x000000);//Set drawing color to black //Declare and initialize some working variables. String keyData = null; int fontHeight = g.getFont().getHeight(); //Number of lines of text that fit on screen. int cntLimit = this.getHeight()/fontHeight; int yOffset = 0; int xOffset = 0; |
A two-column display
Most of the complexity of this method resides in the requirement to create two columns for drawing the text strings. This requires knowledge of the number of strings that will fit from top to bottom on the screen, which in turn requires knowledge of the vertical space occupied by each character. The code in Listing 8 gets the font height and performs that calculation.
Remainder of the overridden paint method
Listing 9 displays the data captured from the user keyboard input in two columns. When the length of the first column exceeds the height of the screen, the display wraps and starts a new column as shown in Figure 3. If the length of the second column exceeds the height of the screen, the data will simply be lost off the bottom of the screen.
Listing 9. Remainder of the overridden paint method.
for(int cnt = 0;cnt < vect.size();cnt++){ keyData = (String)vect.elementAt(cnt);//note cast if(cnt * fontHeight < this.getHeight() - fontHeight){ //Display in first column. yOffset = cnt * fontHeight; xOffset = 5; }else{ //Display in second column yOffset = (cnt - cntLimit) * fontHeight; xOffset = this.getWidth()/2; }//end else //Draw the string on the Canvas. g.drawString(keyData,xOffset,yOffset,0); }//end for loop }//end overridden paint method |
Drawing from top to bottom of the screen
Note that a value of 0 is passed as the fourth parameter to the drawString method. This causes the anchor point location to default to TOP|LEFT.
Since the direction for increasing values of the Y-coordinate is down the screen, the code in Listing 9 extracts the text data from the Vector and draws the text on the screen moving from top to bottom.
|
Overridden keyPressed method
The MyCanvas class inherits an empty method named keyPressed from the Canvas class and overrides that method. Whenever the MyCanvas object is being displayed on the screen and the used presses one of the keys shown in Figure 3, the Canvas object “fires” a keyPressed event, causing the overridden keyPressed method to be called. The overridden keyPressed method is shown in Listing 10.
Listing 10. Overridden keyPressed method.
public void keyPressed(int keyCode){ vect.addElement(getKeyName(keyCode)); this.repaint(); }//end keyPressed }//end member class MyCanvas }//end class Canvas02 |
Behavior of the code in Listing 10
The code in Listing 10:
- Gets the name of the key that was pressed (which may be peculiar to the Sun cell phone emulator).
- Adds that name to the data already in the Vector object.
- Calls the repaint method on the Canvas object.
The call to the repaint method causes the overridden paint method to be executed. As described earlier, the call to the overridden paint method:
- Clears the canvas by painting it white.
- Extracts the text data from the Vector (including the new data).
- Draws the text on the screen in two columns as shown in Figure 3.
Therefore, each time the user presses a key, the screen is re-drawn, causing the contents of the Vector object to be displayed. In this case, the call to the repaint method is not superfluous as it probably was earlier.
When is the paint method called?
As mentioned above, the paint method is called whenever the program code calls the repaint method. However, that is not the only time the paint method is called. It is called at any time that the system needs to cause the Canvas to be repainted by the MIDlet for any reason. For example, if a system screen covers the Canvas temporarily, the paint method will be called to redraw the screen when the system screen goes away.
Run the programs
I encourage you to copy the MIDlet code from Listing 11 and Listing 12. Run the MIDlets in the updated MIDlet development framework named WTKFramework03 that I provided in the lesson titled Using Alerts, Images, Timers, and Gauges in MIDlets (see Resources). Experiment with the MIDlet code, making changes and running your modified MIDlets in the framework program. See if you can explain the results produced by your changes.
Don’t forget that you will need to download and install the latest version of the Sun Java Wireless Toolkit for CLDC (see Resources). As of the date this lesson is being written, the latest version of the toolkit is WTK2.5.2.
Summary
In this lesson, you learned how to use several methods of the Canvas class (including paint and repaint), along with several methods of the Graphics class to draw text and lines on the cell phone screen. You learned how to use anchor point coordinates to control the position of text that is drawn on the screen. You also learned how to handle keyPressed events fired by a Canvas object.
What’s next?
In Part 2 of this lesson, you will learn how to mix image file data and drawn graphics on a cell phone screen. You will learn how to draw various shapes such as rectangles, circles, arcs, filled triangles, and rounded rectangles. You will learn how to use an off-screen image, and how to use the event handling capability of the Canvas class for simple animation. You will also learn how to make you MIDlet animations efficient by minimizing the screen area that must be repainted.
Resources
- Download Sun Java Wireless Toolkit 2.5 for CLDC Release
- MIDlet: From Wikipedia, the free encyclopedia
- MIDlet: According to SCMAD Certification Center
- J2ME Tutorial, Part 1: Creating MIDlets by Vikram Goyal
- Pre-verifying MIDlet code according to Vikram Goyal
- Deploying a MIDlet according to Vikram Goyal
- The Java ME Device Table
- Retrieving MIDlet Attributes by Richard Marejka
- Learning Path: MIDlet Life Cycle
- When Runtime.exec() won’t By Michael C. Daconta
- Connected Limited Device Configuration (CLDC) from Wikipedia
- Mobile Information Device Profile (MIDP) from Wikipedia
- Online API documentation forCLDC 1.0
- Online API documentation forCLDC 1.1
- Online API documentation for MIDP 1.0
- Online API documentation for MIDP 2.0
- Free Online Image Converter
- 62 Event Handling in JDK 1.0.2, The Event Class
- 80 Event Handling in JDK 1.1, A First Look, Delegation Event Model
- 102 Handling Events in Extended Components without Listener Objects
- 1640 The Essence of OOP using Java, Anonymous Classes
- 2570 Getting Started with MIDlets and the Sun Java Wireless Toolkit for CLDC
- 2572 Capturing Output Produced by Programs Running in a Child Process
- 2574 Back to Basics with MIDlets and the Sun Java Wireless Toolkit for CLDC
- 2576 Introduction to the MIDlet User Interface, A First Look
- 2578 Handling Life-Cycle Issues with the MIDlet User Interface
- 2580 Using Alerts, Images, Timers, and Gauges in MIDlets
- 2582 Using Lists in MIDlets
- 2584 Using Forms and Items in MIDlets
- 2586 Programming MIDlets for Interactive Behavior
Complete program listings
Complete listings of the programs discussed in this lesson are shown in Listing 11 and Listing 12 below.
Listing 11. Source code for the MIDlet named Canvas01.
/*Canvas01.java Copyright 2007, R.G.Baldwin The purpose of this program is to illustrate a simple MIDlet using a Canvas object and a Graphics object. It further illustrates the use of anchor point constants to establish the alignment of drawn text. The MIDlet begins by painting the entire screen white. Otherwise, the new drawing would appear on top of what was previously on the screen. Then it sets the drawing color to black. Then it draws eight pairs of graphic objects. Each pair consists of: A line from 0,0 to a specific coordinate value on the canvas. A string of text with the anchor point set to match the end of the line. The text contents of each string give the combination of anchor point constants used to position that particular string. Some text strings also begin with a lower case y- to show the effect of descenders on the alignment of the text string. The eight pairs of graphic objects illustrate the effect of different combinations of the following anchor point constants as well as the impact of lower-case descenders on the alignment produced by the constants: TOP BASELINE BOTTOM LEFT HCENTER RIGHT An anchor point must be specified for each text string that is drawn. The anchor point must be produced by the bitwise inclusive OR of one of the top three vertical anchor constants and one of the bottom three horizontal anchor constants. For example, the following would be a valid anchor point: TOP|RIGHT The actual position and the alignment of the text string are determined by the combination of a pair of specified coordinate values and the bitwise inclusive OR of two anchor constants. The coordinates specify the position that will be assumed by a particular point in the text string. The bitwise inclusive OR of two anchor constants determines which point in the text string will be located at the specified coordinates. The special anchor point value of zero is interpreted to mean TOP|LEFT. A pair of straight lines is used to connect the ends of two groups of sloping lines. This makes it easier to visually determine the location of the anchor point in each text string. This MIDlet illustrates the use of the following methods from the Graphics class: setColor fillRect drawLine drawString It also illustrates the use of the following method from the Canvas class: paint repaint getWidth getHeight The MIDlet displays the canvas for 20 seconds and then enters the destroyed state. Tested using a Java SE 6 compiler, targeted at a V1.4 virtual machine, and WTK 2.5.2 running under Windows XP. *********************************************************/ package Canvas01; import javax.microedition.lcdui.Display; import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; public class Canvas01 extends MIDlet{ Canvas myCanvas; public Canvas01(){ System.out.println("Construct MIDlet"); myCanvas = this.new MyCanvas(); //Guarentee that the screen gets painted. myCanvas.repaint(); }//end constructor public void startApp(){ //Make the Canvas the current display. Display.getDisplay(this).setCurrent(myCanvas); //Sleep for 20 seconds. try{Thread.currentThread().sleep(20000); } catch(Exception e){} //Enter the destroyed state. this.destroyApp(true); }//end startApp public void pauseApp(){ }//end pauseApp public void destroyApp(boolean unconditional){ System.out.println("Destroy MIDlet"); notifyDestroyed(); }//end destroyApp //----------------------------------------------------// //member class class MyCanvas extends Canvas{ public void paint(Graphics g){ //Paint the entire screen white. Otherwise, the new // drawing will simply appear over top of what was // previously on the screen. g.setColor(0xffffff); g.fillRect(0,0,getWidth(),getHeight()); //Set the drawing color to black. g.setColor(0x000000); //Draw text at eight different anchor points. The // text shows the vertical and horizontal constants // required to set the respective anchor points. // In addition, a line is drawn from 0,0 to the // anchor point to visually identify the anchor // point. A lower-case y is used to show the effect // of descenders on the alignment of the text. g.drawLine(0,0,200,20); g.drawString("y-TOP|RIGHT",200,20, Graphics.TOP|Graphics.RIGHT); g.drawLine(0,0,150,40); g.drawString("y-TOP|HCENTER",150,40, Graphics.TOP|Graphics.HCENTER); g.drawLine(0,0,100,60); g.drawString("y-TOP|LEFT",100,60, Graphics.TOP|Graphics.LEFT); g.drawLine(0,0,100,90); g.drawString("y-BOTTOM|LEFT",100,90, Graphics.BOTTOM|Graphics.LEFT); g.drawLine(0,0,100,110); g.drawString("BOTTOM|LEFT",100,110, Graphics.BOTTOM|Graphics.LEFT); g.drawLine(0,0,100,130); g.drawString("y-BASELINE|LEFT",100,130, Graphics.BASELINE|Graphics.LEFT); g.drawLine(0,0,100,150); g.drawString("BASELINE|LEFT",100,150, Graphics.BASELINE|Graphics.LEFT); g.drawLine(0,0,100,170); g.drawString("Special Case of Zero",100,170,0); //Draw straight lines that connect the ends of the // sloping lines. g.drawLine(200,20,100,60); g.drawLine(100,60,100,170); }//end overridden paint method }//end member class MyCanvas }//end class Canvas01 |
Listing 12. Source code for the MIDlet named Canvas02.
/*Canvas02.java Copyright 2007, R.G.Baldwin The purpose of this program is to illustrate the detection and handling of key events on a Canvas object. The MIDlet also demonstrates certain aspects of the FullScreenMode versus the normal mode. A Canvas object is instantiated and set to FullScreenMode. The inherited keyPressed method is overridden to capture a user keystroke, convert the key code to a key name, add the key name to a Vector object, and cause the screen to be repainted each time a keyPressed event occurs. The paint method is overridden to clear the canvas, extract all of the key names from the Vector, and display the key names in two columns by using the drawString method to draw the key names on the Canvas object. Note, on the Sun cell phone emulator, you can terminate the MIDlet by clicking the button on the right that has a picture of a horizontal telephone receiver. When you point to this button, the picture of the telephone receiver should turn red. I did not register an EXIT command listener because I did not want to cause the left soft key to be occupied with a command when in normal mode. Tested using a Java SE 6 compiler, targeted at a V1.4 virtual machine, and WTK 2.5.2 running under Windows XP. *********************************************************/ package Canvas02; import javax.microedition.lcdui.Display; import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.Displayable; import java.util.Vector; public class Canvas02 extends MIDlet{ Canvas myCanvas; public Canvas02(){ System.out.println("Construct MIDlet"); myCanvas = this.new MyCanvas(); //Guarentee that the screen gets painted. myCanvas.repaint(); //Note: The following commands cannot be activated // because there is no CommandListener registered on // the Canvas object. They are here solely to // demonstrate the impact of FullScreenMode versus // normal mode. When the Canvas object is set to // FullScreenMode, as is the case in this MIDlet, // these commands are not displayed. Therefore, even // if a CommandListener were registered on the Canvas, // it would not be possible for the user to activate // the commands. In normal mode, the commands are // displayed. If there was a CommandListener // registered on the Canvas, the user could activate // the commands. You can demonstrate this behavior by // modifying the code to pass true or false to the // setFullScreenMode method in the MyCanvas // constructor. myCanvas.addCommand(new Command("EXIT", Command.EXIT,2)); myCanvas.addCommand(new Command("BACK", Command.BACK,2)); myCanvas.addCommand(new Command("OK",Command.OK,2)); }//end constructor public void startApp(){ //Make the Canvas the current display. Display.getDisplay(this).setCurrent(myCanvas); }//end startApp public void pauseApp(){ }//end pauseApp public void destroyApp(boolean unconditional){ System.out.println("Destroy MIDlet"); notifyDestroyed(); }//end destroyApp //----------------------------------------------------// //Member class class MyCanvas extends Canvas{ Vector vect = new Vector(); MyCanvas(){//constructor //Note: In normal mode, the gray bar where the soft // key commands normally appear is visible at the // bottom of the screen. However, in // FullScreenMode, that gray bar disappears. This // seems it make it impossible for the user to // activate commands on the Canvas when in // FullScreenMode. You can demonstrate this behavior // by either removing the following statement or // modifying the code to pass false to the // setFullScreenMode method. Passing false to the // method will switch the Canvas to normal mode. this.setFullScreenMode(true); }//end constructor public void paint(Graphics g){ //Paint the entire screen white. g.setColor(0xffffff); g.fillRect(0,0,getWidth(),getHeight()); g.setColor(0x000000);//Set drawing color to black //Declare and initialize some working variables. String keyData = null; int fontHeight = g.getFont().getHeight(); //Number of lines of text that fit on screen. int cntLimit = this.getHeight()/fontHeight; int yOffset = 0; int xOffset = 0; //Display the data captured from the user keyboard // input in two columns using graphic display // capabilities. If the length of the second // column exceeds the height of the screen, the // data will simply fall off the bottom of the // screen. for(int cnt = 0;cnt < vect.size();cnt++){ keyData = (String)vect.elementAt(cnt);//note cast if(cnt * fontHeight < this.getHeight() - fontHeight){ //Display in first column. yOffset = cnt * fontHeight; xOffset = 5; }else{ //Display in second column yOffset = (cnt - cntLimit) * fontHeight; xOffset = this.getWidth()/2; }//end else //Draw the string on the Canvas. g.drawString(keyData,xOffset,yOffset,0); }//end for loop }//end overridden paint method //--------------------------------------------------// //Override the keyPressed method to: // capture keystrokes // save them in a Vector object // repaint the canvas. public void keyPressed(int keyCode){ vect.addElement(getKeyName(keyCode)); this.repaint(); }//end keyPressed }//end member class MyCanvas }//end class Canvas02 |
Copyright
Copyright 2008, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
About the author
Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.
Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin’s Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.
In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP). His first job after he earned his Bachelor’s degree was doing DSP in the Seismic Research Department of Texas Instruments. (TI is still a world leader in DSP.) In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.