'double buffering' Sample program in J2ME
By: Charles
The term double buffering refers to a technique for buffering a graphics context before displaying it. The idiom requires that you use two graphics contexts -or buffers - hence its name.You first draw graphics in a secondary graphics context, and later copy its contents to the graphics context that represents the device's display. This secondary graphics context is called an off-screen buffer. An off-screen buffer is one that doesn't render to the display.
The motivation for this technique is performance. Drawing operations can result in frequent updates to the display, causing the user to perceive display flicker. To avoid flicker, you first perform your drawing to an off-screen graphics context, then copy the whole off-screen graphics context to the original device graphics. A copy operation is usually faster than the multitude of drawing operations required of even a relatively complex canvas, so it can be done with almost no perceptible flicker.
The sample program below demonstrates the use of double buffering. It performs some simple drawing functions in an off-screen buffer, then copies the contents of that buffer to the primary graphics context that represents the device's display. Although the drawing routines in this example are relatively simple, a real-life application might perform much more complicated drawing, truly warranting the need for double buffering.
/* Double buffering uses two graphics contexts. The only way to obtain a
second graphics context in MIDP is through the Image class.*/
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import java.io.IOException;/**
Demonstrates double buffering of graphics context for
display on a Canvas.
*/
public class DoubleBufferDemo extends Canvas
implements CommandListener
{
// A constant that represents the color white.
private static final int WHITE =
0xFF << 16 | 0xFF << 8 | 0xFF;
private static Command back =
new Command("Back", Command.BACK, 1);
GraphicsDemo gDemo = GraphicsDemo.getInstance();
private Display display = Display.getDisplay(gDemo);
// The image object to use to obtain an off-screen
// Graphics object.
private Image offscreen;
// A variable used for determining if the implementation
// is automatically double buffered. Holds the value
// true if the implementation automatically does double
// buffering, false otherwise.
private boolean autoDoubleBuffered = true;/**
No-arg constructor.
*/
public DoubleBufferDemo()
{
super();
addCommand(back);
setCommandListener(this);
display.setCurrent(this);
if (!isDoubleBuffered())
{
// If the implementation doesn't automatically
// use double buffering, get an Image so we
// can get an off-screen Graphics from it.
// This Image is mutable! Its dimensions are the
// width and height of this Canvas.
offscreen = Image.createImage(getWidth(), getHeight());
autoDoubleBuffered = false;
}
}
protected void paintClipRect(Graphics g)
{
int clipX = g.getClipX();
int clipY = g.getClipY();
int clipH = g.getClipHeight();
int clipW = g.getClipWidth();
int color = g.getColor();
g.setColor(WHITE);
g.fillRect(clipX, clipY, clipW, clipH);
g.setColor(color);
}
public void paint(Graphics g)
{
Graphics originalG = null;
int width = getWidth();
int height = getHeight();
if (!autoDoubleBuffered)
{
// Save original graphics context and get a new
// off-screen Graphics from the utility Image.
originalG = g;
g = offscreen.getGraphics();
// Clear the clip rectangle using the new Graphics
// object. This way we're using double buffering
// to clear the Canvas, thereby avoiding
// flickering. Clearing the Canvas is drawing
// like all other drawing operations.
paintClipRect(g);
}
else
{
// Clear the Canvas with the original graphics
// because the implementation does double
// buffering automatically.
paintClipRect(g);
}
for (int x = 0, y = 0; (x < width / 2); x = x + 2)
{
g.drawRect(x, y, (width - x) - x, (height - y) - y);
y++; y++;
}
// Drawing the image actually copies the contents of
// the image's off-screen Graphics context to the
// device's Graphics context.
if (!autoDoubleBuffered)
{
originalG.drawImage(offscreen, 0, 0,
Graphics.TOP | Graphics.LEFT);
}
}
public void commandAction(Command c, Displayable d)
{
if (c == back)
{
GraphicsDemo.getInstance().display();
}
}
}
The constructor contains the first code related to double buffering. The statement below, taken from the DoubleBufferDemo no-argument constructor, determines whether the implementation automatically supports double buffering.
if (!isDoubleBuffered())
{
offscreen = Image.createImage(getWidth(),
getHeight());
autoDoubleBuffered = false;
}
If the implementation does support double buffering, the application doesn't need to execute it. The Canvas.isDoubleBuffered() method tells you whether the implementation does double buffering implicitly. Notice the construction of the Image object. This call to Image.createImage() produces a mutable Image object. The application needs a mutable Image because it will perform its drawing in the Image object's Graphics context, which is the off-screen buffer we need. This is the only way to obtain an additional Graphics in MIDP.
The paint() method contains the rest of the double-buffering code. If there is no automatic double buffering, the application must perform it. This requires a second graphics context. The following fragment from the paint() method demonstrates the idiom.
public void paint(Graphics g)
{
...
if (!autoDoubleBuffered)
{
originalG = g;
g = offscreen.getGraphics();
}
else
{
paintClipRect(g);
}
...
}
A temporary variable saves a reference to the original Graphics object, which represents the device's graphics context. The new graphics context is obtained through the Image object constructed earlier. This Graphics is associated with the Image.
Now the paint(Graphics g) method performs its drawing operations to the off-screen Graphics context. When it's done, it copies the contents of the off-screen Graphics to the original Graphics context, which results in rendering to the display. The copy operation is done by the call to the Graphics.drawImage() method. This method says, in effect, "Copy the contents of this image argument's graphics context to me."
The MIDP double buffering mechanism differs from Swing's double buffering. In Swing, you can double-buffer drawing operations on any Component, not just Canvas objects. Swing applications call java.awt.Component.getGraphics() to obtain an off-screen graphics context. The application can draw in this context. It then sets this off-screen graphics context to be the one associated with the native device.
MIDP has no such call. The only reference to a Graphics object that's associated with the native device is the one passed to the paint(Graphics g) method of a Canvas.
Archived Comments
1. int myColor = 0xFFFF00;
paint(Graphics graphics)
{
graphics.setColor(myColor);<
View Tutorial By: krishna mohan at 2010-02-01 05:22:12
2. plz,sent me a sample j2me programm for chnging colour of texr using timers
View Tutorial By: su at 2007-12-19 21:54:30
Comment on this tutorial
- Data Science
- Android
- AJAX
- ASP.net
- C
- C++
- C#
- Cocoa
- Cloud Computing
- HTML5
- Java
- Javascript
- JSF
- JSP
- J2ME
- Java Beans
- EJB
- JDBC
- Linux
- Mac OS X
- iPhone
- MySQL
- Office 365
- Perl
- PHP
- Python
- Ruby
- VB.net
- Hibernate
- Struts
- SAP
- Trends
- Tech Reviews
- WebServices
- XML
- Certification
- Interview
categories
Related Tutorials
Code sample to Send SMS from a J2ME application.
Adding your own Application icon for your J2ME application (jar file)
Play a multimedia file in J2ME Program (Audio/Video) using MMAPI
Using HttpConnection in J2ME (Retrieve web content from a website to a phone)
Using HTTP vs UDP vs Socket in J2ME
RMSCookieConnector - Using Cookies in J2ME
Client Server in J2ME (Socket Programming sample)
Datagrams in J2ME (UDP Programming sample)
POST UTF-8 encoded data to the server in J2ME
Using alerts and tickers in J2ME
Using List to create a Menu and Menu items in J2ME
lists, forms, choices, gauges, text fields, text boxes in J2ME
Timer and TimerTask example in J2ME