📄 apr01_ericg.txt
字号:
J 2 M E T E C H T I P S
TIPS, TECHNIQUES, AND SAMPLE CODE
WELCOME to the Java Developer Connection(sm) (JDC)
Java(tm) 2 Platform, Micro Edition (J2ME(tm))
Tech Tips, for April 16, 2001. This issue covers:
* Using Timers
* An Introduction to the High-Level User Interface
API: Alerts and Tickers
The J2ME Tech Tips are written by Eric Giguere
(http://www.ericgiguere.com), an engineer at iAnywhere
Solutions, inc., and author of the book "Java 2 Micro
Edition: Professional Developer's Guide."
You can view this issue of the J2ME Tech Tips on the Web at
http://java.sun.com/jdc/J2METechTips/2001/tt0416.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USING TIMERS
One of the improvements in version 1.3 of the Java 2 Platform,
Standard Edition (J2SE) are classes that make it simpler to
schedule tasks for execution by a background thread. The Mobile
Information Device Profile (MIDP) also includes these new
classes, so Java 2 Platform, Micro Edition (J2ME) developers also
benefit.
Tasks are defined and scheduled using two classes:
java.util.TimerTask and java.util.Timer. The TimerTask class is
an abstract class that serves as the base class for all scheduled
tasks. The Timer class creates and manages threads on which the
tasks are executed.
To define a task, create a subclass of TimerTask that implements
the run method, for example:
import java.util.*;
public class MyTask extends TimerTask {
public void run() {
System.out.println( "Running the task" );
}
}
If the run method looks familiar, it's because TimerTask
implements the java.lang.Runnable interface. The Timer class
invokes the run method to run the task. The method should perform
its task and exit as soon as possible because only one task for
each Timer object can execute at any time.
After you define a task, you schedule it by creating an instance
of Timer and invoking the schedule method, as in the following:
import java.util.*;
Timer timer = new Timer();
TimerTask task = new MyTask();
// wait ten seconds before executing...
timer.schedule( task, 10000 );
// wait five seconds before executing, then
// execute every ten seconds
timer.schedule( task, 5000, 10000 );
There are four versions of the schedule method; each schedules
tasks to occur at a specific time (specified using a Date
object) or after a specific delay (in milliseconds). You can
schedule the tasks to occur once or to repeat indefinitely at
specified periods. There is also a scheduleAtFixedRate method
that schedules the task for repeated execution in intervals
relative to the scheduled execution time of the first execution.
If an execution is delayed (say for garbage collection), two or
more subsequent executions are scheduled at shorter intervals to
"catch up."
Each Timer object creates and manages a single background thread.
A single timer is usually all that a single application needs,
but there is no limit on the number of timers you can create.
You can stop a timer at any time and terminate its background
thread by calling the timer's cancel method. Note that once
stopped, a timer cannot be restarted -- you must create a new
Timer object and reschedule the tasks you want executed. Timer
objects are thread-safe; there's no need to perform any explicit
synchronization if you're calling a Timer object on different
threads.
After you schedule a task, you can stop its execution by calling
its cancel method. This is often done within the run method of
the task. Calling the cancel method within the run method
guarantees that the current execution of the task is the last
one; it also allows the method to be called at any point, even
before the task's first scheduled execution.
Here's a simple example of a MIDlet that uses a timer to perform
a simple simulation of a moving starfield. The stars are drawn
as points using low-level graphics APIs. For further discussion
about these low-level APIs, see the March 19, 2001 J2ME Tech Tip
"Using the MIDP Low-level User Interface API"
(http://java.sun.com/jdc/J2METechTips/2001/tt0319.html#tip2).
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
public class TimerDemo extends MIDlet {
Display display;
StarField field = new StarField();
FieldMover mover = new FieldMover();
Timer timer = new Timer();
public TimerDemo() {
display = Display.getDisplay( this );
}
protected void destroyApp( boolean unconditional ) {
}
protected void startApp() {
display.setCurrent( field );
timer.schedule( mover, 100, 100 );
}
protected void pauseApp() {
}
public void exit(){
timer.cancel(); // stop scrolling
destroyApp( true );
notifyDestroyed();
}
class FieldMover extends TimerTask {
public void run(){
field.scroll();
}
}
class StarField extends Canvas {
int height;
int width;
int[] stars;
Random generator = new Random();
boolean painting = false;
public StarField(){
height = getHeight();
width = getWidth();
stars = new int[ height ];
for( int i = 0; i < height; ++i ){
stars[i] = -1;
}
}
public void scroll() {
if( painting ) return;
for( int i = height-1; i > 0; --i ){
stars[i] = stars[i-1];
}
stars[0] = ( generator.nextInt() % ( 3 * width ) ) / 2;
if( stars[0] >= width ){
stars[0] = -1;
}
repaint();
}
protected void paint( Graphics g ){
painting = true;
g.setColor( 0, 0, 0 );
g.fillRect( 0, 0, width, height );
g.setColor( 255, 255, 255 );
for( int y = 0; y < height; ++y ){
int x = stars[y];
if( x == -1 ) continue;
g.drawLine( x, y, x, y );
}
painting = false;
}
protected void keyPressed( int keyCode ){
exit();
}
}
}
The TimerDemo MIDlet uses a Timer object, timer, to schedule
execution of the TimerTask subclass, FieldMover, every 100
milliseconds. FieldMover updates and repaints the starfield,
extending it downward in each interval. This gives the
illusion of a moving starfield.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AN INTRODUCTION TO THE HIGH-LEVEL USER INTERFACE API: ALERTS AND
TICKERS
The Mobile Information Device Profile (MIDP) includes both
a low-level user interface (UI) API and a high-level UI API. The
low-level API gives you complete access to a device's screen and
to raw key and pointer events. However, no user interface
controls are available with the low-level API -- your application
must explicitly draw buttons and other familiar controls. This is
the price you pay for the flexibility of the low-level API.
The situation is reversed with the high-level API. It provides
simple user interface controls, but no direct access to the
screen or to raw input events. The controls are fairly abstract
to account for the differences in screen size and input methods
between various MIDP devices. The MIDP implementation decides how
to draw the control and how to manage user input.
You can use both low-level and high-level APIs in a single
MIDlet, just not at the same time. For example, games that rely
on the low-level API to control the screen can also use the
high-level API for online help or to display high scores.
Business applications that use the high-level API for UI
controls can also use the low-level API to draw graphs.
For more information about the low-level UI API, see the J2ME
Tech Tip for March 19, 2001, "Using the MIDP Low-Level User
Interface API"
(http://java.sun.com/jdc/J2METechTips/2001/tt0319.html#tip2).
The following tip introduces the high-level UI API,
and uses two basic controls to do that: alerts and tickers.
An alert is basically a message dialog, that is, a way of
presenting a single string to the user (along with an optional
image or sound). Alerts display warnings, errors, alarms,
notices, or confirmations. Your application's user interface is
disabled while an alert is displayed. The alert then either
times out automatically (the timeout value is programmable) or
remains on screen until the user explicitly dismisses it.
You display an alert by creating an instance of the
javax.microedition.lcdui.Alert class. You specify a title (which
can be null) as a parameter to the constructor. A number of
setter methods are available to define the alert's properties.
For example:
import javax.microedition.lcdui.*;
Image icon = ...; // code omitted
Alert msg = new Alert( "Error!" );
msg.setImage( icon );
msg.setString( "No connection was possible." );
msg.setTimeout( 5000 ); // in milliseconds
msg.setType( AlertType.ERROR );
You don't need to set all properties. For example, the image is
optional, and can be null. (Even if you set the image, the
device might not be able to display it.) However, at a minimum,
you should always define a title and a message string. As far as
other properties:
o The type of the alert, an instance of the AlertType class,
determines the sound to play when the alert is displayed; it
can be null.
o The timeout value defaults to a system-specific value, which
you can determine at runtime by calling the
Alert.getDefaultTimeout method. If you specify a timeout value,
it should be the number of milliseconds to display the alert,
or the special value Alert.FOREVER for a modal alert.
You can also specify all properties, except for the timeout
value, in the constructor. For example:
Alert msg = new Alert( "Error!",
"No connection was possible.",
icon,
AlertType.ERROR );
msg.setTimeout( Alert.FOREVER ); // make it modal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -