ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

MIDP GUI Programming, Part 3
Pages: 1, 2

Double Buffering

The double buffering technique is often used to perform smooth effect animation. In this technique, you do not draw to the display, but instead to a copy of the display (an off-screen buffer) that is maintained in memory. When you are done drawing to the buffer, you then copy the contents of the buffer to the display. The rationale here is that copying the contents of memory to the display is faster than drawing by using primitives.



To implement double buffering, first create a mutable image with the size of the screen:

int width = getWidth(  );
int height = getHeight(  );
Image buffer = Image.createImage(width, height);

Next, obtain a graphics context for the buffer:

Graphics gc = buffer.getGraphics(  );

Now, you can draw to the buffer:

Previously in this series:

MIDP GUI Programming, Part 2 -- This is the second in a series of excerpts from Chapter 5 of Learning Wireless Java. It discusses how the various classes in the high-level MIDP API can be used to create GUI components.

MIDP GUI Programming, Part 1 -- This is the first in a series of excerpts from Chapter 5 of Learning Wireless Java. Why not use AWT? Well, MIDP contains its own abbreviated GUI, which is much different from AWT. This chapter excerpt introduces you to the MIDP GUI APIs.

// animate
// ..
gc.drawRect(20, 20, 25, 30);

When you need to copy the buffer to the screen, you can override the paint( ) method to draw the buffer to the device display:

public void paint(Graphics g) {
   g.drawImage(buffer, 0, 0, 0);
}

Note that some MIDP implementations are already double-buffered, and therefore this work may not be necessary. To check if the graphics are double-buffered by an implementation, use the Canvas. isDoubleBuffered( ) method.

Threading Issues

The MIDP GUI APIs are thread-safe. In other words, the methods can be called at any time from any thread. The only exception is the serviceRepaints( ) method of the Canvas class, which immediately calls the paint( ) method to force immediate repainting of the display. This means that if paint( ) tries to synchronize on any object that is already locked by the application when serviceRepaints( ) is called, the application will deadlock. To avoid deadlocks, do not lock an object that will be used by the paint() method if serviceRepaints( ) is involved.

In addition, you can use the callSerially( ) method of the Display class to execute code after all pending repaints are served, as shown in the following segment of code:

class TestCanvas extends Canvas implements Runnable {
   void doSomething(  ) {
      // code fragment 1
      callSerially(this);
   }
 
   public void run(  ) {
      // code fragment 2
   }
}

Here, the object's run( ) method will be called after the initial call.

Fonts

Fonts cannot be created by applications. Instead, an application requests a font based on attributes (i.e., size, face, style) and the underlying implementation will attempt to return a font that closely resembles the requested font. The Font class represents various fonts and metrics. There are three font attributes defined in the Font class, and each may have different values, as follows:

Face
MONOSPACE, PROPORTIONAL, SYSTEM
Size
SMALL, MEDIUM, LARGE
Style
BOLD, ITALIC, PLAIN, UNDERLINED

For example, to specify a medium size font, use Font.SIZE_MEDIUM, and to specify an italic style, use Font.STYLE_ITALIC, and so on. Values for the style attributes may be combined using the OR (|) operator; values for the other attributes may not be combined. For example, the value of this style attribute specifies a plain, underlined font:

STYLE_PLAIN | STYLE_UNDERLINED

However, the following is illegal:

SIZE_SMALL | SIZE_MEDIUM

This is also illegal:

FACE_SYSTEM | FACE_MONOSPACE

Each font in the system is actually implemented individually, so in order to obtain an object representing a font, use the getFont( ) method. This method takes three arguments for the font face, size, and style, respectively. For example, the following snippet of code obtains a Font object with the specified face, style, and size attributes:

Font font = Font.getFont(FACE_SYSTEM, 
  STYLE_PLAIN, SIZE_MEDIUM);

If a matching font does not exist, the implementation will attempt to provide the closest match, which is always a valid Font object.

Once a font is obtained, you can use methods from the Font class to retrieve information about that font. For example, you can use the methods getFace(), getSize( ), and getStyle( ) to retrieve information about the face, size, and style of the font, respectively.

Let's look at an example. The code in Example 5-3 subclasses the Canvas class. In this example, the drawing color is set to white, a rectangle is drawn in the current color, then the drawing color is set to black. The rest of the code draws the system fonts on the device screen, as shown in Figure 2.

Screen shot.
Figure 2. Drawing system fonts on the device screen.

Example 5-3: Using fonts

import javax.microedition.lcdui.*;
 
public class FontCanvas extends Canvas {
   public void paint(Graphics g) {
      g.setColor(0xffffff);
      g.fillRect(0, 0, getWidth(), getHeight(  ));
      g.setColor(0x000000);
 
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
          Font.SIZE_LARGE));
      g.drawString("System Font", 0, 0, g.LEFT | g.TOP);
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
          Font.SIZE_MEDIUM));
      g.drawString("Medium Size", 0, 15, g.LEFT | g.TOP);
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD,
          Font.SIZE_MEDIUM));
      g.drawString("Bold Style", 0, 30, g.LEFT | g.TOP);
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC,
          Font.SIZE_MEDIUM));
      g.drawString("Italic Style", 0, 45, g.LEFT | g.TOP);
      g.setFont(Font.getFont(Font.FACE_SYSTEM,
          Font.STYLE_UNDERLINED, Font.SIZE_MEDIUM));
      g.drawString("Underlined Style", 0, 60, g.LEFT | g.TOP);
   }
}

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class FontMidlet extends MIDlet {
   public FontMidlet(  ) { // constructor
   }
 
   public void startApp(  ) {
      Canvas canvas = new FontCanvas(  );
      Display display = Display.getDisplay(this);
      display.setCurrent(canvas);
   }
 
   public void pauseApp(  ) {
   }
 
   public void destroyApp(boolean unconditional) {
   }
}

Guidelines for GUI Programming for MIDP Devices

As we close this chapter, keep in mind some important guidelines when designing MIDlets with graphical API functionality:

  • Be sure to make the MIDlet user interface simple and easy to use. Remember that your applications will likely be used by novice users who probably haven't used a J2ME-enabled phone and may not be familiar with its interface.

  • Use the high-level API as much as possible, so that your MIDlets are portable across different handheld devices.

  • If your application requires you to use the low-level API, keep to the platform-independent part of the low-level API. This means that your MIDlets should not assume any other keys than those defined in the Canvas class. We'll discuss this in more detail in the next chapter.

  • MIDlets should never assume any specific screen size; instead, they should query the size of the display and adjust accordingly.

  • Entering alphanumeric data through a handheld device can be tedious. If possible, provide a list of choices from which the user can select.


Previously in this series:

MIDP GUI Programming, Part 2 -- This is the second in a series of excerpts from Chapter 5 of Learning Wireless Java. It discusses how the various classes in the high-level MIDP API can be used to create GUI components.

MIDP GUI Programming, Part 1 -- This is the first in a series of excerpts from Chapter 5 of Learning Wireless Java. Why not use AWT? Well, MIDP contains its own abbreviated GUI, which is much different from AWT. This chapter excerpt introduces you to the MIDP GUI APIs.

View catalog information for Learning Wireless Java


Return to ONJava.com.