//4.3.2  Screenʹù    TickerExample.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class TickerExample extends MIDlet implements CommandListener{
  Command cmdExit;
  public void startApp(){
    cmdExit = new Command("Exit ",Command.EXIT,0);
	    TextBox textBox = new TextBox("Hello Midlet", "Hello,World!!", 256, 0);
    textBox.addCommand(cmdExit);
    textBox.setCommandListener((CommandListener)this);

Ticker TickerExample = new Ticker("A Ticker scrolls slowly...");
	Screen s = (Screen)textBox;
	s.setTicker(TickerExample);

    Display.getDisplay(this).setCurrent(textBox);
  }

  public void pauseApp(){}
  public void destroyApp(boolean unconditional){}

  public void commandAction(Command cmd,Displayable s){
    if (cmd == cmdExit)
	{
      destroyApp(false);
	      notifyDestroyed();
	}
  }
}

//4.4.3  ʹť
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class Commander extends MIDlet implements CommandListener
{
  Command cmdExit;
  public void startApp()
  { 
    cmdExit = new Command("Exit", Command.SCREEN, 0);
    TextBox textBox = new TextBox("Hello Midlet", "Hello,World!!", 256, 0);
    textBox.addCommand(cmdExit);
    textBox.setCommandListener((CommandListener)this);
    Display.getDisplay(this).setCurrent(textBox);
  } 
  public void pauseApp(){} 
  public void destroyApp(boolean unconditional){} 
  public void commandAction(Command command, Displayable screen) 
  { 
    if(command==cmdExit){ 
      destroyApp(false);
      notifyDestroyed(); 
    }
  }
}

//4.5.2  ıʾ
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class TextBoxExample extends MIDlet {
    Display display;
    TextBox t1, t2, t3, t4, t5, t6, cur;				// ı
    Command prn, one, two, three, four, five, six;		// 尴ť

    public void destroyApp (boolean unconditional) {}

    public void pauseApp () {}

    public void startApp () {
        display = Display.getDisplay(this);

    t1 = new TextBox("ANY", "", 15, TextField.ANY);		// ı
    t2 = new TextBox("EMAILADDR", "", 15, TextField.EMAILADDR);
        try {
            t3 = new TextBox("NUMERIC", "-123", 15, TextField.NUMERIC);
        } catch (IllegalArgumentException  e) {
            System.out.println("no error");
        }
		// ı
    t4 = new TextBox("PHONENUMBER", "", 15, TextField.PHONENUMBER);
    t5 = new TextBox("URL", "", 15, TextField.URL);
    t6 = new TextBox("PASSWORD", "", 15, 
                         (TextField.ANY|TextField.PASSWORD));
		   // ť
        prn  = new Command("PRT", Command.OK, 1);
        one  = new Command("ANY",  Command.SCREEN, 10);
        two  = new Command("EMAILADDR",  Command.SCREEN, 20);
        three= new Command("NUMERIC",Command.SCREEN, 30);
        four = new Command("PHONENUMBER", Command.SCREEN, 40);
        five = new Command("URL", Command.SCREEN, 50);
        six  = new Command("PASSWORD", Command.SCREEN, 60);
        
 		// ťĴ
        CommandListener cl = new CommandListener() {
            public void commandAction(Command x, Displayable s) {
                if (x == prn) {
                    System.out.println(cur.getString());
                } else if (x == one) {
                    cur = t1;
                    display.setCurrent(t1);
                } else if (x == two) {
                    cur = t2;
                    display.setCurrent(t2);
                } else if (x == three) {
                    cur = t3;
                    display.setCurrent(t3);
                } else if (x == four) {
                    cur = t4;
                    display.setCurrent(t4);
                } else if (x == five) {
                    cur = t5;
                    display.setCurrent(t5);
                } else if (x == six) {
                    cur = t6;
                    display.setCurrent(t6);
                }
            }
        };

			// Ϊť
        t1.addCommand(prn);
        t1.addCommand(one);
        t1.addCommand(two);
        t1.addCommand(three);
        t1.addCommand(four);
        t1.addCommand(five);
        t1.addCommand(six);
        t1.setCommandListener(cl);

        t2.addCommand(prn);
        t2.addCommand(one);
        t2.addCommand(two);
        t2.addCommand(three);
        t2.addCommand(four);
        t2.addCommand(five);
        t2.addCommand(six);
        t2.setCommandListener(cl);

        t3.addCommand(prn);
        t3.addCommand(one);
        t3.addCommand(two);
        t3.addCommand(three);
        t3.addCommand(four);
        t3.addCommand(five);
        t3.addCommand(six);
        t3.setCommandListener(cl);

        t4.addCommand(prn);
        t4.addCommand(one);
        t4.addCommand(two);
        t4.addCommand(three);
        t4.addCommand(four);
        t4.addCommand(five);
        t4.addCommand(six);
        t4.setCommandListener(cl);

        t5.addCommand(prn);
        t5.addCommand(one);
        t5.addCommand(two);
        t5.addCommand(three);
        t5.addCommand(four);
        t5.addCommand(five);
        t5.addCommand(six);
        t5.setCommandListener(cl);

        t6.addCommand(prn);
        t6.addCommand(one);
        t6.addCommand(two);
        t6.addCommand(three);
        t6.addCommand(four);
        t6.addCommand(five);
        t6.addCommand(six);
        t6.setCommandListener(cl);

        cur = t1;
        display.setCurrent(t1);
    }
}


//4.6.3  ʾʹõ
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class TwoAlerts extends MIDlet implements CommandListener {
  private Display mDisplay;
  private TextBox mTextBox;
  private Alert mTimedAlert;		// 屨
  private Alert mModalAlert;
  private Command mAboutCommand,mGoCommand,mExitCommand;
  public TwoAlerts(){			// ť
    mAboutCommand =new Command("About ",Command.SCREEN,1);
    mGoCommand =new Command("Go ",Command.SCREEN,1);
    mExitCommand =new Command("Exit ",Command.EXIT,2);
  }
  public void startApp(){
    mDisplay =Display.getDisplay(this);
    mTextBox =new TextBox("TwoAlerts "," ",1,TextField.ANY);	// ı
    mTextBox.addCommand(mAboutCommand);	// ť
    mTextBox.addCommand(mGoCommand);
    mTextBox.addCommand(mExitCommand);
    mTextBox.setCommandListener(this);
    mTimedAlert =new Alert("Network error ",		// ɱ
    "A network error occurred.Please try again.",null,AlertType.INFO);
    mModalAlert =new Alert("About TwoAlerts ",	// ɱ
    "TwoAlerts is a simple MIDlet that demonstrates the use of Alerts.",
    null,AlertType.INFO);
    mModalAlert.setTimeout(Alert.FOREVER);
    mDisplay.setCurrent(mTextBox);
  }
  public void pauseApp(){}
  public void destroyApp(boolean unconditional){}

	  // ťĴ
  public void commandAction(Command c,Displayable s){
  if (c ==mAboutCommand)
    mDisplay.setCurrent(mModalAlert);
  else if (c ==mGoCommand)
    mDisplay.setCurrent(mTimedAlert,mTextBox);
  else if (c ==mExitCommand)
    notifyDestroyed();
  }
}


//4.7.3  ʹб
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class ListDemo extends MIDlet{
  private Display display;
  private int mode = List.IMPLICIT;
	  // ť
  private Command exitCommand = new Command( "Exit",Command.SCREEN, 2 );
  private Command selectCommand = new Command( "Select",Command.OK, 1 );
  private Command nextCommand = new Command( "Next",Command.SCREEN, 2 );

  public ListDemo(){}

  protected void destroyApp( boolean unconditional )
    throws MIDletStateChangeException {
	  exitMIDlet();
 }

  protected void pauseApp(){}

  protected void startApp() throws MIDletStateChangeException {
     if( display == null ){ // first time called...
       initMIDlet();
    }
  }

	   // ʾб
   private void initMIDlet(){
     display = Display.getDisplay( this );
     display.setCurrent( new SampleList( mode ) );
  }

   public void exitMIDlet(){
     notifyDestroyed();
  }

   public static final String[] items = {
    "First", "Second", "Third", "Fourth"	// бʾַ
  };

   class SampleList extends List implements CommandListener {
     private int mode;
     SampleList( int mode ){
       super( "", mode, items, null );
       // ť
       addCommand( exitCommand );
       addCommand( selectCommand );
       addCommand( nextCommand );
       setCommandListener(this);

       switch( mode ){
         case IMPLICIT:
           setTitle( "Implicit" );
           break;
         case EXCLUSIVE:
           setTitle( "Exclusive" );
           break;
         case MULTIPLE:
           setTitle( "Multiple" );
           break;
      }

       this.mode = mode;
    }

         // ťĴ
     public void commandAction( Command c,Displayable d ){
       if( c == exitCommand ){
         exitMIDlet();
      } else if( c == selectCommand ){
         showSelection( false );
      } else if( c == SELECT_COMMAND ){
         showSelection( true );
      } else if( c == nextCommand ){
         if( mode == List.IMPLICIT ){
           mode = List.EXCLUSIVE;
        } else if( mode == List.EXCLUSIVE ){
           mode = List.MULTIPLE;
        } else {
           mode = List.IMPLICIT;
        }
         display.setCurrent( new SampleList(mode));
      }
    }
     // ʾûѡѡ
     private void showSelection( boolean implicit ){
       Alert alert = new Alert(implicit?"Implicit Selection":"Explicit Selection" );
       StringBuffer buf = new StringBuffer();

       if( mode == MULTIPLE ){
         boolean[] selected = new boolean[ size() ];
         getSelectedFlags( selected );

         for( int i = 0; i < selected.length; ++i ){  // ѡ
           if( selected[i] ){
             if( buf.length() == 0 ){
               buf.append("You selected: " );
            } else {
               buf.append( ", " );
            }

             buf.append( getString( i ) );
          }
        }

         if( buf.length() == 0 ){
           buf.append( "No items are selected." );
        }
      } else {
         buf.append("You selected ");
         buf.append(getString(getSelectedIndex()));
      }

       alert.setString(buf.toString());
       alert.setTimeout(Alert.FOREVER);

       display.setCurrent(alert,display.getCurrent());
    }
  }
}


//4.8.2  ʽ
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class Gauge1 extends MIDlet implements CommandListener{
  private Display display;       // display  
  private Form fmMain;       //  
  private Command cmExit;    
  private Gauge gaSound;      

  public Gauge1(){
    display = Display.getDisplay(this);
    // Create the gauge and exit command
    gaSound = new Gauge("Sound Level", true, 30, 4);     // ɱ
    cmExit = new Command("Exit", Command.EXIT, 1);  // ť
    // Create the form, add gauge & exit command, listen for events
    fmMain = new Form("");
    fmMain.addCommand(cmExit);   // ť
    fmMain.append(gaSound);
    fmMain.setCommandListener(this);
  }
  // ʼMIDlet
  public void startApp(){
    display.setCurrent(fmMain);
  }
  public void pauseApp(){}  
  public void destroyApp(boolean unconditional){}
  public void commandAction(Command c, Displayable s){
    if (c == cmExit){
      destroyApp(false);
        notifyDestroyed();
    }
  }
}


//ǽʽ
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Timer;
import java.util.TimerTask;

public class Gauge2 extends MIDlet implements CommandListener{
  private Display display;        //display 
  private Form fmMain;            // 
  private Command cmExit;      
  private Command cmStop;      
  private Gauge gaProgress;      // ָʾ
  private Timer tm;         
  private DownloadTimer tt; 

  public Gauge2(){
    display = Display.getDisplay(this);
    // Create the gauge, exit and stop command
    gaProgress = new Gauge("Download Progress", false, 20, 1);  // ɱ
    cmExit = new Command("Exit", Command.EXIT, 1);		// ť
    cmStop = new Command("Stop", Command.STOP, 1);        
    // 壬ߣȻ¼
    fmMain = new Form("");
    fmMain.append(gaProgress);
    fmMain.addCommand(cmStop);
    fmMain.setCommandListener(this);
  }

  // ʼMIDletʱ
  public void startApp(){
    display.setCurrent(fmMain);
    // һ1000 ΪִмĶʱ 
    tm = new Timer();
    DownloadTimer tt = new DownloadTimer();
    tm.scheduleAtFixedRate(tt, 0, 1000);          
  }

  public void pauseApp(){}  
  public void destroyApp(boolean unconditional){}

      // ť
  public void commandAction(Command c, Displayable s){
    if (c == cmExit){
      destroyApp(false);
        notifyDestroyed();
    }
    else if (c == cmStop){
      tm.cancel();
      fmMain.removeCommand(cmStop);    
      fmMain.addCommand(cmExit);    
      gaProgress.setLabel("Download Cancelled!");
    }      
  }
  
  /*--------------------------------------------------
  * ʱ
  *-------------------------------------------------*/  
  private class DownloadTimer extends TimerTask{
    public final void run(){
      // ǰֵǷ񳬹ֵ
      if (gaProgress.getValue() < gaProgress.getMaxValue())
        gaProgress.setValue(gaProgress.getValue() + 1);        
      else{
        // ɾstop ť֮Exitť
        fmMain.removeCommand(cmStop);    
        fmMain.addCommand(cmExit);        
        // ıߵı 
        gaProgress.setLabel("Download Complete!");        
        // ֹͣʱ
        cancel();      
      }
    }
  }
}


//4.9.2  ûַУ    NumericInputForm.java
import javax.microedition.lcdui.*;

public class NumericInputForm extends Form implements ItemStateListener {
    public static final Command DONE_COMMAND =     //Doneť
             new Command( "Done", Command.OK, 1 );  
    public static final Command CANCEL_COMMAND =  //Cancelť
             new Command( "Cancel", Command.CANCEL, 1 );

    private String[]   masks;
    private int[]      digits;
    private Command    done;
    private Command    cancel;
    private TextField  field;
    private StringItem match;

    public NumericInputForm( String title,String label,String[] masks,String value ){
        this( title, label, masks, value,null, null );
    }

    public NumericInputForm( String title,String label,String[] masks, String value,
                             Command done,Command cancel ){
        super( title );
        this.masks  = masks;
        this.done   = ( done != null ? done : DONE_COMMAND );
        this.cancel = ( cancel != null ? cancel: CANCEL_COMMAND );
        digits = new int[ masks.length ];
        int maxlen = 0;
        for( int i = 0; i < masks.length; ++i ){		// νм
            int mlen = countDigitsInMask( masks[i] );
            if( mlen > maxlen ) maxlen = mlen;
            digits[i] = mlen;
        }

        field = new TextField( label,value,maxlen,TextField.PHONENUMBER );
        append( field );  // ı
        match = new StringItem( null, "" );
        append( match );
        adjustState();
        addCommand( this.cancel );
        setItemStateListener( this );
    }

    protected void adjustState(){
        String val = field.getString();
        String applied = null;

        for( int i = 0; i < masks.length; ++i ){   // 鵱ǰ״̬
            applied = matches( val, digits[i], masks[i] );
            if( applied != null ){
                break;
            }
        }

        if( applied != null ){
            match.setText( applied );
            addCommand( done );
        } else {
            match.setText( "" );
            removeCommand( done );
        }
    }

    // Ҫٸ
    private int countDigitsInMask( String mask ){
        int count = 0;

        for( int i = 0; i < mask.length(); ++i ){
            char ch = mask.charAt( i );
            if( ch == '#' || Character.isDigit( ch ) ){
                ++count;
            }
        }

        return count;
    }

    // ֵ
    public String getMaskedValue(){
        return match.getText();
    }

    // ԭʼĸ
    public String getRawValue(){
        return field.getString();
    }

    public void itemStateChanged( Item item ){
        adjustState();
    }

    // ĸǷı׼
    protected String matches( String value,int digits,String mask ){
        if( value.equals( mask ) ) return value;

        int vlen = value.length();
        if( vlen != digits ) return null;  // Ȳͬ
        int mlen = mask.length();
        int vindex = 0;

        StringBuffer b = new StringBuffer( mlen );
        for( int i = 0; i < mlen; ++i ){   // μÿĸ
            char mch = mask.charAt( i );
            char vch = mch;

            if( mch == '#' ){
                vch = value.charAt( vindex++ );
            } else if( Character.isDigit( mch ) ){
                vch = value.charAt( vindex++ );
                if( mch != vch ) return null;
            }

            b.append( vch );
        }

        return b.toString();
    }

    // ıַеַ
    public void setRawValue( String value ){
        field.setString( value );
        adjustState();
    }
}


//4.9.3  绰
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;

// Բͬĸʽ绰
public class NumericInputTest extends MIDlet {

    private Display display;
    private Command exitCommand =    // ť
                        new Command( "Exit",
                                   Command.EXIT, 1 ); 
    private Command okCommand =
                         new Command( "OK",   // ť
                                     Command.OK, 1 );

    public NumericInputTest(){
    }

        // MIDlet˳ʱִ
    protected void destroyApp( boolean unconditional )
                   throws MIDletStateChangeException {
        exitMIDlet();
    }

    protected void pauseApp(){
    }

    protected void startApp()
                   throws MIDletStateChangeException {
        if( display == null ){ 
            initMIDlet();
        }
    }

        // ʼMIDlet
    private void initMIDlet(){
        display = Display.getDisplay( this );
        display.setCurrent( new PromptForPhone() );
    }

    public void exitMIDlet(){
        notifyDestroyed();
    }

    private String[] phoneMasks =         // 绰
                       new String[]{"#######","###-#######"};

    // ͵绰ʼֵ
    class PromptForPhone extends NumericInputForm
                        implements CommandListener {

        public PromptForPhone(){
            super( "Test", "Enter a phone number:",
                   phoneMasks, "" );
            setCommandListener( this );
        }

        // ûѡdoneߡcancelťʱִ
        public void commandAction( Command c,
                                   Displayable d ){
            if( c == CANCEL_COMMAND ){
                exitMIDlet();
            } else {
                Alert a = new Alert( "Result" );
                a.setString( "You entered the number " +   // ʾѡ
                             getMaskedValue() +
                             " from the string " +
                             getRawValue() );
                a.setTimeout( Alert.FOREVER );
                display.setCurrent( a, this );
                setRawValue( "" );
            }
        }
    }
}


//4.10.4  ʹںʱ
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class DateFieldTest extends MIDlet {

    private Display display;    
    // ť 
    private Command exitCommand = new Command( "Exit", Command.EXIT, 1 ); 
    private Command okCommand =new Command( "OK", Command.OK, 1 );
    private Command cancelCommand =new 
Command("Cancel", Command.CANCEL, 1 );
    public DateFieldTest(){}
    protected void destroyApp( boolean unconditional )
                    throws MIDletStateChangeException {
        exitMIDlet();
    }
    protected void pauseApp(){}
 
    protected void startApp()
                    throws MIDletStateChangeException {
        if( display == null ){ // һε
            initMIDlet();
        }
    }
    // MIDletʼʱִ
    private void initMIDlet(){
        display = Display.getDisplay( this );
        testList = new TestList();
        display.setCurrent( testList );
    }

    public void exitMIDlet(){
        notifyDestroyed();
    }
    public static Date clearDate( Date d ){
        Calendar c = Calendar.getInstance();
        c.setTime( d );
        c.set( Calendar.MONTH, Calendar.JANUARY );  // 
        c.set( Calendar.DAY_OF_MONTH, 1 );     // 
        c.set( Calendar.YEAR, 1970 );  // 
        return c.getTime();
    }
  // ںʱϳһDateʵ
    public static Date combineDateTime( Date date, Date time ){
        Calendar cd = Calendar.getInstance();
        Calendar ct = Calendar.getInstance();

        cd.setTime( date );  // 
        ct.setTime( time );  // ʱ

        ct.set( Calendar.MONTH, cd.get( Calendar.MONTH ) );
        ct.set( Calendar.DAY_OF_MONTH, cd.get(Calendar.DAY_OF_MONTH));
        ct.set( Calendar.YEAR, cd.get( Calendar.YEAR ) );
        return ct.getTime();
    }
    
    static final String[] testLabels = {  // ʾַ
        "Current date",
        "Current time",
        "Current date/time",
        "Edit date",
        "Edit time",
        "Edit date/time",
    };

    private TestList testList;
    private Date     editDate;

        // ʾҪеĲΪ
    class TestList extends List
                   implements CommandListener {
        public TestList(){
            super( "DateField Tests", IMPLICIT, testLabels, null );
            addCommand( exitCommand );
            setCommandListener( this );
        }

        public void commandAction( Command c, Displayable d ){
            if( c == exitCommand ){
                exitMIDlet();
            } else if( c == List.SELECT_COMMAND ){
                // ָʾںģʽ
                int     which = getSelectedIndex();
                String  label = getString( which );
                int     mode = ( which % 3 ) + 1;
                boolean save = ( which > 2 );

                display.setCurrent(new Edit( save, label, mode ) );
            }
        }
    }

    // ༭ڡʱ
    class Edit extends Form implements CommandListener {

        public Edit( boolean save, String label, int mode ){  // ༭
            super( label );
            this.save = save;
            Date d = editDate;
            if( !save ){
                d = new Date();
            }

            dateField = new DateField( null, mode );
            append( dateField );

            if( d != null ){
                if( mode == DateField.TIME ){
                    d = clearDate( d );
                }
                dateField.setDate( d );
            }
            addCommand( okCommand );
            if( save ){
                addCommand( cancelCommand );
            }
            setCommandListener( this );
        }
       // 
        public void commandAction( Command c, Displayable d ){
            Alert alert = null;
            Date  date = dateField.getDate();

            if( 
              save && date != null && c == okCommand ){
                if( editDate != null ){
                   int mode = dateField.getInputMode();
                    if( mode == DateField.DATE ){
                        editDate = combineDateTime( 
                                      date, editDate );
                    } else if( 
                              mode == DateField.TIME ){
                        editDate = combineDateTime( 
                                      editDate, date );
                    } else {
                        editDate = date;
                    }
                } else {
                    editDate = date;
                }

                Calendar cal = Calendar.getInstance();
                cal.setTime( editDate );

                alert = new Alert( "New date/time" );
                alert.setString( 
                 "The saved date/time is now " + cal );
                alert.setTimeout( Alert.FOREVER ); //ʾǰõںʱ
            }

            if( alert != null ){
                display.setCurrent( alert, testList );
            } else {
                display.setCurrent( testList );
            }
        }

        private DateField dateField;
        private boolean   save;
    }
}
public class MultiAlert extends MIDlet {
    Display      display;
    Command      exitCommand = new Command( "Exit", Command.EXIT,
                                                             1 );
   	    public MultiAlert() {
        display = Display.getDisplay( this );
        router = new AlertRouter( display );

 	    timer1.schedule( new AlertTrigger( "Alert 1", 
                             "This is alert #1" ), 5000, 10000 );
        timer2.schedule( new AlertTrigger( "Alert 2", 
                              "This is alert #2" ), 5000, 7000 );
        timer3.schedule( new AlertTrigger( "Alert 3", 
                              "This is alert #3" ), 5000, 9000 );
    } 


//4.11.3  ǿģ
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 ) {}
   // MIDletʼʱִ
    protected void startApp() {
        display.setCurrent( field );
        timer.schedule( mover, 100, 100 );
    }

    protected void pauseApp() {}

    public void exit(){
        timer.cancel(); // ֹͣʱ
        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();
        }
    }
}


//4.12  ۺӡƱ۸ٳ
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;

public class StockWatcher extends MIDlet {
  Display display;
  Ticker ticker = new Ticker( "" );
  Command exitCommand = new Command("Exit", Command.EXIT, 1 );
  Timer        timer = new Timer();  // һʱ
  StockChecker checker = new StockChecker();
  TickerForm   form = new TickerForm();
  Alert        alert = new Alert( "Stock Alert!" );  // һ
  public StockWatcher() {
    display = Display.getDisplay( this );
    alert.setTimeout( Alert.FOREVER );  // öʱģʽ
  }
  protected void destroyApp( boolean unconditional ) { }
  protected void startApp() {
    display.setCurrent( form );
    timer.schedule( checker, 0, 30000 ); // öʱʱ
  }
  protected void pauseApp() { }
  public void exit(){
    timer.cancel(); //ֹͣʱ
    destroyApp( true );
    notifyDestroyed();
  }
  // ʾ
  class TickerForm extends Form implements CommandListener {
    public TickerForm(){
      super( "Stock Watch" );
      setTicker( ticker );
      addCommand( exitCommand );
      setCommandListener( this );
    }
    public void commandAction( Command c, Displayable d ){
      exit();
    }
 }
                    
 // Ʊļ۸۸񳬹趨ֵĻʾ
 class StockChecker extends TimerTask {
   Random       generator = new Random();
   int          sybsValue = 20000;  // 趨ĹƱ۸
   int          sunwValue = 30000;  // 趨ĹƱ۸
   int          ibmValue = 40000;  // 趨ĹƱ۸
   StringBuffer buf = new StringBuffer();

   public void run(){
     String values = getStockValues();
     ticker.setString( values );  // ıƱ۸
     if( sybsValue < 18000 || sybsValue > 22000 ||  // Ʊ۸Ƿ񳬹趨ֵ
                sunwValue < 28000 || sunwValue > 32000 ||
                ibmValue < 38000 || ibmValue > 42000 ){
       alert.setString( values ); // 趨ֵ
     }

     if( !alert.isShown() ){
       display.setCurrent( alert, form );
     }
   }

       // ȡùƱ۸
   private String getStockValues(){
     sybsValue = randomStockValue( sybsValue );  // 漴ɹƱ۸
     sunwValue = randomStockValue( sunwValue );
     ibmValue = randomStockValue( ibmValue );

     buf.setLength( 0 );
     appendValue( "SYBS", sybsValue );
     appendValue( "SUNW", sunwValue );
     appendValue( "IBM", ibmValue );

     return buf.toString();
   }

   // 漴ɹƱļ۸
   private int randomStockValue( int oldVal ){
     int incr1 = ( generator.nextInt() % 2 );
     int incr2 = ( generator.nextInt() % 16 );

     if( incr1 < 1 ){
       oldVal -= incr1 * 1000;
     } else {
       oldVal += ( incr1 - 2 ) * 1000;
     }

     if( incr2 < 8 ){
       oldVal -= incr2 * 250;
     } else {
       oldVal += incr2 * 250;
     }

     return oldVal;
   }

   private void appendValue( String stock, int val ){
     buf.append( stock );
     buf.append( ' ' );
     buf.append( Integer.toString( val / 1000 ) );
     buf.append( '.' );
     buf.append( Integer.toString( val % 1000 ) );
     buf.append( ' ' );
   }
 }
} 
