By Eric Giguerejuly 14, 2002
The low-level user-interface APIs of the Mobile Information Device Profile (MIDP) allow you to control exactly what is drawn on the screen through the Canvas class. Sometimes, though, you also want to have control over when the drawing occurs, or .
Generally, it is the device that controls when painting occurs A painting event is triggered when any of a number of things occur -. The canvas is shown for the first time, a menu that was hiding part of the canvas is withdrawn, or an alert is dismissed. The device then invokes the canvas's paint method, passing it a Graphics object initialized to draw on the correct parts of the display. The method does the drawing and returns as quickly as possible. Note that no key or pointer events are processed While The Painting Occurs - Execution of Events, Including Repaint Notifications, IS Always Serialized.
The Simplest Way to Handle Repaints Is To Let The System Schedule The THEM. All You Do Is Tell The System That The Canvas Needs Repainting by Calling The Canvas.Repaint () Method:
Canvas c = ...
C.Repaint (20, 20, 50, 50); // x, y, w, h
The system queues a paint request for the given area. (Another version of the repaint method takes no arguments and queues a paint request for the entire canvas.) If you mark two or more areas for repainting within a short span of time, the system may combine the paint requests into a single request to paint the union of the two areas (the smallest rectangle containing both). At some point the system invokes the canvas's paint method, passing it a Graphics object whose clipping area is set to the area that Needs repainting.you can call, Because The MIDP User-Interface Classes Aready Swing Classes You May ALREADY BE FAMILIAR WITH.
Sometimes, though, waiting for the system to call the paint method is not good enough. Perhaps you want to update the display immediately in response to some user input. You can force an update to occur at any point by calling the serviceRepaints () method :
Canvas c = .....
C.Repaint (0, 0, 20, 30);
C.ServiceRepaints (); // Paint it now
If the canvas is visible and one or more paint requests are queued, serviceRepaints () causes the system to invoke the canvas's paint method as soon as possible. ServiceRepaints () does not return until the paint method returns.
Note that you have no way to control - or even know - which thread the system uses when it invokes the canvas's paint method Often, it uses the same thread that called serviceRepaints () The system may choose to use a different thread.. , however, and block the initiating thread until the painting is finished. A deadlock can occur if the paint method requires access to an object that the initiating thread has locked. You must therefore be careful about accessing synchronized objects in your paint () method. What if you want to execute some code after the display is repainted Calling the code from the canvas's paint method may not work as you expect it -? the display may be updated only after the paint method returns, especially if the system does automatic double -Buffering for Flicker-Free Output. a better tactic is to use the display.callserly () Method, Passing it an Object That Implements The Standard Java.lang.Runnable Interface:
Runnable r = ....
Display d = ....
D.CallSerially (R);
Each callSerially () invocation adds the given object to a system-maintained list. As it processes events, the system removes an object from the list and invokes its run method, effectively serializing the call with system-generated events. Furthermore, if a repaint is pending when the object is added to the list, its run method is not invoked until after the display has been repainted -. this order is guaranteed by the MIDP specification You can use this feature to animate images, as in this example adapted from The Midp Specification:
Public class Animation Extends Canvas Implements Runnable {
Private image [] frames;
Private Int next = 0;
PRIVATE BOOLEAN GO = FALSE;
Public animation (image [] frames) {this.frames = frame;
}
Protected Void Paint (Graphics G) {
g.drawImage (frames [next], 0, 0, g.top | g.left);
}
Public void startanimation () {
GO = true;
Repaint ();
Callser or (this);
}
Public void stopanimation () {
GO = false;
}
Public void run () {// called after previous repaint IS
Finished
IF (go) {
IF ( next> = frames.length) next = 0;
Repaint ();
Callser or (this);
}
}
}
One Problem With this Approach to Animation, However, IS That The Animation Rate - The Number of Frames Painted Per Second - Is Device-Dependent. It May Be Better To Use A Timer-Based Approach.
About the Author: Eric Giguere is a software developer for iAnywhere Solutions, a subsidiary of Sybase, where he works on Java technologies for handheld and wireless computing He holds BMath and MMath degrees in Computer Science from the University of Waterloo and has written extensively on. COMPUTING TOPICS.