Java/J2ME/Timer
Содержание
A simple class that shows an example of using a Timer and a TimerTask.
<source lang="java">
/*
* 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(); } }
}
</source>
Demonstrate simple animation using a Timer and TimerTask
<source lang="java">
/*--------------------------------------------------
- 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); }
}
</source>
Timer and animation
<source lang="java">
/* 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(); }
} }
</source>
Timer and sticker
<source lang="java">
/*
* 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)"); } } }
}
</source>
Timer Template
<source lang="java">
/*--------------------------------------------------
- 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"); } }
}
</source>