Java/J2ME/Timer
Содержание
A simple class that shows an example of using a Timer and a TimerTask.
/*
* Copyright (c) 2000-2001 Sun Microsystems, Inc. All Rights Reserved.
*/
import java.lang.*;
import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* A simple class that shows an example of using a Timer and
* a TimerTask.
*
* This MIDlet creates two gauges. One gauge gaugeOne,
* sets elements from low to high. The other, gaugeTwo,
* set elements from high to low. In effect, this has
* gaugeOne "going up", and gaugeTwo "going down."
*
* The two timers fire at different intervals.
*
* There are two commands on our form:
*
* OK: toggles whether the times are active or not.
* EXIT: exits the MIDlet.
*/
public class TimerMIDlet extends MIDlet implements CommandListener {
// number of elements in gauge
final private static int GAUGE_MAX = 10;
private boolean timersRunning; // tracks state of timers
private Display myDisplay; // handle to the display
private Gauge gaugeOne; // "going up" gauge
private Gauge gaugeTwo; // "going down" gauge
private Form myScreen; // form on which to
// place gauges
private Command cmdOK; // OK command
private Command cmdExit; // EXIT command
private Timer timer;
private MyTimerTask timerTaskOne;
private MyTimerTask timerTaskTwo;
/**
* Internal class that provides a TimerTask.
*/
private class MyTimerTask extends TimerTask {
private Gauge myGauge; // reference to gauge
private boolean goUp; // if true, go up
private int num; // number of times called
/**
* Public constructor: stores "direction" and a reference to
* a gauge.
*/
public MyTimerTask(Gauge g, boolean up) {
myGauge = g;
goUp = up;
}
/**
* As the timer fires, this method is invoked. Set gauge
* based on goUp
*/
public void run() {
num++;
myGauge.setValue(goUp ?
GAUGE_MAX -(num % GAUGE_MAX) :
num % GAUGE_MAX);
}
}
/**
* Public constructor: gets handle to display,
* creates form, gauges, and commands.
*/
public TimerMIDlet() {
myDisplay = Display.getDisplay(this);
myScreen = new Form("TimerMIDlet");
gaugeOne = new Gauge("Up Gauge",
false,
GAUGE_MAX,
0);
myScreen.append(gaugeOne);
gaugeTwo = new Gauge("Down Gauge",
false,
GAUGE_MAX,
GAUGE_MAX);
myScreen.append(gaugeTwo);
cmdOK = new Command("OK", Command.OK, 1);
cmdExit = new Command("Exit", Command.EXIT, 1);
myScreen.addCommand(cmdOK);
myScreen.addCommand(cmdExit);
myScreen.setCommandListener(this);
}
/**
* Changes the state of timers to/from active to/from
* not-active.
*/
private void flipFlop() {
if (timersRunning) {
timerTaskOne.cancel();
timerTaskTwo.cancel();
timer.cancel();
timersRunning = false;
} else {
timer = new Timer();
timerTaskOne = new MyTimerTask(gaugeOne, false);
timerTaskTwo = new MyTimerTask(gaugeTwo, true);
timer.schedule(timerTaskOne, 0, 1000);
timer.schedule(timerTaskTwo, 0, 1500);
timersRunning = true;
}
}
/**
* Called by the system to start our MIDlet.
* @exception MIDletStateChangeException
*/
protected void startApp() throws MIDletStateChangeException {
myDisplay.setCurrent(myScreen);
flipFlop();
}
/**
* Called by the system to pause our MIDlet.
* No actions required by our MIDLet.
*/
protected void pauseApp() {}
/**
* Called by the system to end our MIDlet.
* No actions required by our MIDLet.
*/
protected void destroyApp(boolean unconditional) {}
/***
* Respond to command selections. Process two commands:
*
* OK: flip flop the timers to/from active
* EXIT: exit this MIDlet
*
*/
public void commandAction(Command c, Displayable d) {
if (c == cmdOK) {
flipFlop();
} else if (c == cmdExit) {
destroyApp(false);
notifyDestroyed();
}
}
}
Demonstrate simple animation using a Timer and TimerTask
/*--------------------------------------------------
* Animation.java
*
* Demonstrate simple animation using
* a Timer and TimerTask
*
* Example from the book: Core J2ME Technology
* Copyright John W. Muchow http://www.CoreJ2ME.ru
* You may use/modify for any non-commercial purpose
*-------------------------------------------------*/
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Animation extends MIDlet
{
private Display display; // The display
private AnimationCanvas canvas; // Canvas
private Timer tm; // Timer
private AnimateTimerTask tt; // Task
public Animation()
{
display = Display.getDisplay(this);
canvas = new AnimationCanvas(this);
// Create task that fires off every 1/10 second
tm = new Timer();
tt = new AnimateTimerTask(canvas);
tm.schedule(tt, 0, 100);
}
protected void startApp()
{
display.setCurrent(canvas);
}
protected void pauseApp()
{ }
protected void destroyApp(boolean unconditional)
{ }
public void exitMIDlet()
{
destroyApp(true);
notifyDestroyed();
}
}
/*--------------------------------------------------
* AnimateTimerTask.java
*
* Change location of bouncing ball on the canvas
*
* Example from the book: Core J2ME Technology
* Copyright John W. Muchow http://www.CoreJ2ME.ru
* You may use/modify for any non-commercial purpose
*-------------------------------------------------*/
class AnimateTimerTask extends TimerTask
{
private AnimationCanvas canvas;
public AnimateTimerTask(AnimationCanvas canvas)
{
this.canvas = canvas;
}
/*--------------------------------------------------
* Determine next location of the ball.
* If the ball reaches any edge, change the color
* Track how many times we"ve switced directions
*-------------------------------------------------*/
public final void run()
{
// If past the right edge or prior to left edge...
if ((canvas.x_loc + canvas.radius + canvas.x_dir > canvas.getWidth()) ||
(canvas.x_loc - canvas.radius + canvas.x_dir < 0))
{
canvas.x_dir = -canvas.x_dir;
canvas.changeColor();
canvas.directionChanged++;
}
// If past the bottom or before the top...
if ((canvas.y_loc + canvas.radius + canvas.y_dir > canvas.getHeight()) ||
(canvas.y_loc - canvas.radius + canvas.y_dir < 0))
{
canvas.y_dir = -canvas.y_dir;
canvas.changeColor();
canvas.directionChanged++;
}
// Update the new x and y locations
canvas.x_loc += canvas.x_dir;
canvas.y_loc += canvas.y_dir;
canvas.repaint();
}
}
/*--------------------------------------------------
* AnimationCanvas.java
*
* Show a ball that bounces around on a canvas
* Each time we hit a wall we change the ball color
* We also clear the screen after "n" number of
* hits against the wall
* The "left" and "right" keys change the ball size
* The "Fire" key resets the display, however,
* it leaves the ball size the same.
*
* Example from the book: Core J2ME Technology
* Copyright John W. Muchow http://www.CoreJ2ME.ru
* You may use/modify for any non-commercial purpose
*-------------------------------------------------*/
class AnimationCanvas extends Canvas implements CommandListener
{
private Animation midlet; // Main midlet
private Command cmExit; // Exit midlet
private int keyFire, // Reset ball
keyRight, // Increase ball radius
keyLeft; // Decrease ball radius
private boolean clearBackground = false; // Clear background
private Random random; // Random number
int x_loc, // Current x & y locations
y_loc,
radius, // Ball radius
red, // rgb colors
green,
blue,
x_dir, // Next x & y positions of ball
y_dir,
start_x, // Where ball starts
start_y,
directionChanged = 0; // How many times we"ve hit a wall
private static final int MAX_CHANGES = 50;
/*--------------------------------------------------
* Constructor
*-------------------------------------------------*/
public AnimationCanvas(Animation midlet)
{
// Save reference to main midlet
this.midlet = midlet;
random = new java.util.Random();
// Determine starting location and direction of ball
init();
radius = 7;
// Create exit command and "Fire" key
cmExit = new Command("Exit", Command.EXIT, 1);
keyFire = getKeyCode(FIRE);
keyRight = getKeyCode(RIGHT);
keyLeft = getKeyCode(LEFT);
addCommand(cmExit);
setCommandListener(this);
}
/*--------------------------------------------------
* Paint a new ball, clearing the screen as asked
*-------------------------------------------------*/
protected void paint(Graphics g)
{
// Max edge hits, reset everything
if (directionChanged > MAX_CHANGES)
init();
// Clear the background
if (clearBackground)
{
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
clearBackground = !clearBackground;
}
// Set color and draw another ball
g.setColor(red, green, blue);
g.fillArc( x_loc, y_loc, radius, radius, 0, 360);
}
/*--------------------------------------------------
* Initialize starting location and direction of ball
*-------------------------------------------------*/
private void init()
{
// Start close to the middle
x_loc = getWidth() / 2;
y_loc = getHeight() / 2;
// The direction the ball is heading
x_dir = (random.nextInt() % 10);
if (x_dir == 0) x_dir = 1;
y_dir = (random.nextInt() % 10);
if (y_dir == 0) y_dir = 1;
directionChanged = 0;
clearBackground = true;
changeColor();
}
/*--------------------------------------------------
* Change the colors.
* I am counting on the implemention to substitute
* a use-able color if any of these are out of the
* devices supported range
*-------------------------------------------------*/
protected void changeColor()
{
// The shift is to remove any sign (negative) bit
red = (random.nextInt() >>> 1) % 256;
green = (random.nextInt() >>> 1) % 256;
blue = (random.nextInt() >>> 1) % 256;
}
/*--------------------------------------------------
* Event handling
*-------------------------------------------------*/
public void commandAction(Command c, Displayable d)
{
if (c == cmExit)
midlet.exitMIDlet();
}
/*--------------------------------------------------
* Reset ball is "Fire" key is pressed
*-------------------------------------------------*/
protected void keyPressed(int keyCode)
{
// Restart
if (keyCode == keyFire)
init();
// Decrease ball size
else if (keyCode == keyLeft)
radius = Math.max(1, --radius);
else if (keyCode == keyRight)
// Increase ball size
radius = Math.min(getWidth() / 4, ++radius);
}
}
Timer and animation
/* License
*
* Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
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();
}
}
}
Timer and sticker
/*
* TimerMIDlet.java Copyright (c) 2000 Sun Microsystems, Inc. All Rights
* Reserved.
*
* Author: Srikanth Raju
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not disclose such
* Confidential Information and shall use it only in accordance with the terms
* of the license agreement you entered into with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.rumand;
import javax.microedition.lcdui.rumandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.Ticker;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class TimerMIDlet extends MIDlet implements CommandListener {
private Display display = null;
private Ticker stockTicker = null;
private String[] _stocks = { "SUNW", "ORCL", "NOK", "MOT" };
private String[] _prices = { "9", "11", "9.25", "14.5" };
private static final Command exitCommand = new Command("Exit",
Command.STOP, 0);
private static final Command backCommand = new Command("Back",
Command.BACK, 0);
private static final Command doneCommand = new Command("Done", Command.OK,
0);
private Timer stockRefresh = null;
private StockRefreshTask stockRefreshTask = null;
private int refresh_interval = 10000; // 1000 = 1 second
private List menu = null;
private ChoiceGroup _updatesChoices = null;
private Form _updatesForm = null;
private String _currentMenu = null;
public TimerMIDlet() {
}
public void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
menu = new List("Stock Menu", Choice.IMPLICIT);
menu.append("Updates", null);
menu.append("Add Stocks", null);
menu.append("Remove Stocks", null);
menu.addCommand(exitCommand);
menu.setCommandListener(this);
// Make the ticker
stockTicker = new Ticker(makeTickerString());
menu.setTicker(stockTicker);
display.setCurrent(menu);
_currentMenu = "Stock Menu";
_updatesForm = new Form("Updates");
_updatesChoices = new ChoiceGroup("Update Interval:", Choice.EXCLUSIVE);
_updatesChoices.append("Continuous", null); // will be 10 seconds
_updatesChoices.append("15 minutes", null);
_updatesChoices.append("30 minutes", null);
_updatesChoices.append("1 hour", null);
_updatesChoices.append("3 hours", null);
_updatesForm.setTicker(stockTicker);
_updatesForm.append(_updatesChoices);
_updatesForm.addCommand(backCommand);
_updatesForm.addCommand(doneCommand);
_updatesForm.setCommandListener(this);
//Set up and start the timer to refresh the stock quotes
stockRefreshTask = new StockRefreshTask();
stockRefresh = new Timer();
stockRefresh.schedule(stockRefreshTask, 0, refresh_interval);
}
public String makeTickerString() {
String retString = new String();
for (int i = 0; i < _stocks.length; i++) {
retString += _stocks[i];
retString += " @ ";
retString += _prices[i];
retString += " ";
}
return retString;
}
public void pauseApp() {
// free memory used by these objects
display = null;
stockRefresh = null;
stockRefreshTask = null;
}
public void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
notifyDestroyed();
}
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
try {
destroyApp(false);
} catch (MIDletStateChangeException msce) {
System.out.println("Error in detroyApp(false) ");
msce.printStackTrace();
}
notifyDestroyed();
} else if (c == backCommand) {
_currentMenu = "Stock Menu";
display.setCurrent(menu);
} else if (c == doneCommand) {
switch (_updatesChoices.getSelectedIndex()) {
case 0:
refresh_interval = 10000;
break;
case 1:
refresh_interval = 900000;
break;
case 2:
refresh_interval = 1800000;
break;
case 3:
refresh_interval = 3600000;
break;
case 4:
refresh_interval = 10800000;
break;
default:
break;
}
stockRefreshTask.cancel();
stockRefreshTask = new StockRefreshTask();
stockRefresh.schedule(stockRefreshTask, 0, refresh_interval);
display.setCurrent(menu);
_currentMenu = "Stock Menu";
} else {
List shown = (List) display.getCurrent();
switch (shown.getSelectedIndex()) {
case 0: // Updates
display.setCurrent(_updatesForm);
_currentMenu = "Updates";
break;
case 1: // Add Stock
System.out.println("Add Stock... ");
_currentMenu = "Add Stock";
break;
case 2: // Remove Stock
System.out.println("Remove Stock... ");
_currentMenu = "Remove Stock";
break;
}
}
}
/**
* This is an extention of the TimerTask class which runs when called by
* Timer. It refreshes the stock info for each stock from the quote server
* and checks to see if any of the alerts should be fired.
*/
class StockRefreshTask extends TimerTask {
/**
* Execute the Timer"s Task
*/
public void run() {
try {
// Just return if the database is empty
if (_stocks.length == 0)
return;
else {
for (int i = 0; i < _stocks.length; i++) {
System.out.println("Stock price for symbol: "
+ _stocks[i] + " is: " + _prices[i]);
}
}
} catch (Exception e) {
System.out.println("error("UPDATE FAILED", 2000)");
}
}
}
}
Timer Template
/*--------------------------------------------------
* TimerTemplate.java
*
* Test all six Timer scheduling options
*
* Example from the book: Core J2ME Technology
* Copyright John W. Muchow http://www.CoreJ2ME.ru
* You may use/modify for any non-commercial purpose
*-------------------------------------------------*/
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class TimerTemplate extends MIDlet implements CommandListener
{
private Display display; // Our display
private Form fmMain; // Main form
private Command cmExit; // Exit midlet
private Command cmStop; // Stop the timer
private Timer tm; // Timer
private TestTimerTask tt; // Task
private int count = 0; // How many times has task run
public TimerTemplate()
{
display = Display.getDisplay(this);
// Create main form
fmMain = new Form("Timer Test");
fmMain.append("waiting...\n");
// Create commands and add to form
cmExit = new Command("Exit", Command.EXIT, 1);
cmStop= new Command("Stop", Command.STOP, 2);
fmMain.addCommand(cmExit);
fmMain.addCommand(cmStop);
fmMain.setCommandListener(this);
//------------------------------------------------------
// Option #1 - One time task with delayed start
// Create a timer that will go off in 5 seconds
//------------------------------------------------------
tm = new Timer();
tt = new TestTimerTask();
tm.schedule(tt,5000);
//------------------------------------------------------
// Option #2 - Fixed-delay repeating task with delayed start
// Create a timer that will go off in 5 seconds
// Repeating every 3 seconds
//------------------------------------------------------
// tm = new Timer();
// tt = new TestTimerTask();
// tm.schedule(tt,5000, 3000);
//------------------------------------------------------
// Option #3 - Fixed-rate repeating task with delayed start
// Create a timer that will go off in 5 seconds
// Repeating every 3 seconds
//------------------------------------------------------
// timer = new Timer();
// tt = new TestTimerTask();
// timer.scheduleAtFixedRate(tt,5000, 3000);
//------------------------------------------------------
// Option #4 - One time task at specified date
// Create timer that starts at current date
//------------------------------------------------------
// timer = new Timer();
// tt = new TestTimerTask();
// timer.schedule(tt, new Date());
//------------------------------------------------------
// Option #5 - Fixed-delay repeating task starting
// at a specified date
// Create timer that starts at current date
// Repeating every 3 seconds
//------------------------------------------------------
// timer = new Timer();
// tt = new TestTimerTask();
// timer.schedule(tt, new Date(), 3000);
//------------------------------------------------------
// Option #6 - Fixed-rate repeating task starting
// at a specified date
// Create timer that starts at current date
// Repeating every 3 seconds
//------------------------------------------------------
// timer = new Timer();
// tt = new TestTimerTask();
// timer.scheduleAtFixedRate(tt, new Date(), 3000);
}
/*--------------------------------------------------
* Show the main Form
*-------------------------------------------------*/
public void startApp ()
{
display.setCurrent(fmMain);
}
/*--------------------------------------------------
* Shutting down. Cleanup all we created
*-------------------------------------------------*/
public void destroyApp (boolean unconditional)
{
}
/*--------------------------------------------------
* No pause code necessary
*-------------------------------------------------*/
public void pauseApp ()
{ }
/*--------------------------------------------------
* Process events for the main form
*-------------------------------------------------*/
public void commandAction(Command c, Displayable d)
{
if (c == cmStop)
{
tm.cancel();
}
else if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
}
/*--------------------------------------------------
* TestTimerTask Class - Run the task
*-------------------------------------------------*/
private class TestTimerTask extends TimerTask
{
public final void run()
{
fmMain.append("run count: " + ++count + "\n");
}
}
}