Browse DevX
Sign up for e-mail newsletters from DevX


Get Down with the MIDP Low-level User Interface API

MIDP provides a low-level API for fine-grained control over the application user interface. However, applications wanting to make use of these features also inherit a lot of responsibility and risk. Find out the benefits and pitfalls of using the MIDP low-level APIs.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

IDP provides a lot of efficiency and flexibility when building user interfaces. The efficiency part can be seen in what MIDP calls the high-level user interface controls, which is what I discussed last month. This month I will explore the flexibility side of MIDP user interfaces in what MIDP calls the low-level user interface APIs. The MIDP low-level user interface APIs provide much more fine-grained control and nearly limitless customization over an application's user interface. However, there are risks to be managed and tradeoffs to be made when using the low-level APIs. In this article I explore the effort involved in creating low-level user interfaces and discuss some of the implications and risks you are likely to encounter.

The low-level user interface is essentially composed of the Canvas class and a handful of support classes such as Graphics, Font, and Image. The supporting classes are used within an instance of Canvas to create different visual effects.

Canvas is an abstract class. In order to create a user interface using the low-level APIs, an application must create a subclass of Canvas and implement the paint() method. The paint() method is the only method requiring implementation. An instance of Graphics, for example, is passed as a parameter to paint(), which provides access to the device drawing capabilities that allow for directly interacting with the display at the pixel level.

The nice thing about working with the MIDP low-level classes is that very complex user interfaces can be created with only a few classes. However, there are caveats to using this approach. Take the following example, which draws a string on the screen.

public void paint(Graphics graphics) { graphics.drawString("This is a very boring MIDlet "+ "that is nearly putting me to sleep!", 0, 0, Graphics.TOP|Graphics.LEFT); }

Figure 1 shows the MIDlet running in the J2ME Wireless Toolkit where the Canvas has been set as the current display. Although the MIDlet paints the string to the screen there are a few problems that immediately begin to surface.

Figure 1. Overlap: Here's an example of using a Canvas to write some text. However, the Canvas was not cleared first and so the text was drawn over the existing image.
Figure 2. Set to Black: Here I called Graphics.fillRect() to clear the screen. However, because the color is set to black for both the fillRect() and drawString() calls, the text disappears.

The first problem is that the Canvas was not cleared before writing the sentence. As a result, the string painted directly onto the existing image, which happened to be the application launch screen of the Application Management Software (AMS). In the next example, I add a line of code to clear the screen. This technique fills the entire screen with the same color pixels.

public void paint(Graphics graphics) { graphics.fillRect(0, 0, getWidth(), getHeight()); graphics.drawString("This is a very boring MIDlet "+ "that is nearly putting me to sleep!", 0, 0, Graphics.TOP|Graphics.LEFT); }

But now I have a new problem. The screen seems to have gone blank (see Figure 2). What happened is the Canvas filled the screen with pixels of the same color, but the current Canvas color happened to be set to black. Then, when the drawString() method was called, the text was drawn in black as well, having no visible effect at all. To get the desired effect, I'm going to have to manipulate the colors.

Playing with Color

Figure 3. Hue Knew? The color values in the color bar correspond to the different calls to setColor() (see left).
Color and grayscale effects can be manipulated using calls to setColor() and setGrayScale(), respectively. setColor() takes three parameters that describe the desired RGB (red, green, blue) values. In calls to setColor(), a value between 0 and 255 is passed for each RGB color dimension. Passing different values will cause the corresponding color to become more or less saturated in the result. For example a call with the values setColor(0, 100, 255) means the color will have no red, about 40 percent green, and 100 percent blue. A call with setColor(255, 0, 0) will be bright red. Figure 3 shows a palate of colors corresponding to following lines of code:

· graphics.setColor(255,255,255); · graphics.setColor(0,0,0); · graphics.setColor(100,100,100); · graphics.setColor(255,0,0); · graphics.setColor(0,255,0); · graphics.setColor(0,0,255);

Figure 4. Contrast: Setting the background color to white and the text color to black means this time the user can see the text when it writes.
Calls to setGrayScale() require only a single parameter that describes the desired balance of white and black. The gray scale range is 0 to 255, where 0 is black and 255 is white.

With an idea of how setColor() works, I now can add code to first clear the screen to a white background and then paint black text on top of the white background (see Figure 4).

public void paint(Graphics graphics) { graphics.setColor(255,255,255); graphics.fillRect(0, 0, getWidth(), getHeight()); graphics.setColor(0,0,0); graphics.drawString("This is a very boring MIDlet "+ "that is nearly putting me to sleep!", 0, 0, Graphics.TOP|Graphics.LEFT); }

Now things are looking better. The AMS image is cleared by the call to fillRect(), turning the background to white, and the text is now displaying in black.

However, there is one more thing I need to fix. The string is too long for the screen. The Graphics.drawString() method does not support line wrapping, so I'll have to handle it myself. With an example this simple, I can probably get away with splitting the sentence into two parts and calling drawstring() twice. However, I still need to figure out how far down to start drawing the next line. I could guess that 10 or 15 pixels would be sufficient; however, there are more scientific ways of figuring this out using font metrics.

Thanks for your registration, follow us on our social networks to keep up-to-date