// ClockMIDlet.java (c) Kari Laitinen // http://www.naturalprogramming.com // 2002-11-?? File created. // 2009-09-29 This program was improved so that clock hand positions // are calculated with trigonometrical functions. // The old version of the program is in ClockOldMIDlet.java // 2009-10-02 Last modification. // This program displays a clock to the screen. A thread is used to // redraw the clock several times a second. import java.util.* ; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; class ClockCanvas extends Canvas implements Runnable { Thread thread_that_runs_the_clock ; boolean thread_must_be_executed = false ; int canvas_width, canvas_height ; int clock_center_point_x, clock_center_point_y ; public ClockCanvas() { setFullScreenMode( true ) ; canvas_width = getWidth() ; canvas_height = getHeight() ; clock_center_point_x = canvas_width / 2 ; clock_center_point_y = canvas_height / 2 + 10 ; } public synchronized void start_animation_thread() { if ( thread_that_runs_the_clock == null ) { thread_that_runs_the_clock = new Thread( this ) ; thread_must_be_executed = true ; thread_that_runs_the_clock.start() ; } } public void stop_animation_thread() { if ( thread_that_runs_the_clock != null ) { thread_must_be_executed = false ; thread_that_runs_the_clock.interrupt() ; thread_that_runs_the_clock = null ; } } public void run() { while ( thread_must_be_executed == true ) { repaint() ; try { // You should increase sleep period if you think // that this clock consumes too much computing power. Thread.sleep( 200 ) ; // Suspend for 0.2 second. } catch ( InterruptedException caught_exception ) { // No actions to handle the exception. } } } public void paint( Graphics graphics ) { String[] days_of_week = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ; String[] names_of_months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ; Calendar time_now = Calendar.getInstance() ; int current_year = time_now.get( Calendar.YEAR ) ; int current_day = time_now.get( Calendar.DAY_OF_MONTH ) ; int month_index = time_now.get( Calendar.MONTH ) ; int number_of_day_of_week = time_now.get( Calendar.DAY_OF_WEEK ) ; String current_month = names_of_months[ month_index ] ; String current_day_of_week = days_of_week[ number_of_day_of_week - 1 ] ; int current_hours = time_now.get( Calendar.HOUR_OF_DAY ) ; int current_minutes = time_now.get( Calendar.MINUTE ) ; int current_seconds = time_now.get( Calendar.SECOND ) ; int current_milliseconds = time_now.get( Calendar.MILLISECOND ) ; graphics.setColor( 200, 200, 255 ) ; // light blue graphics.fillRect( 0, 0, canvas_width, canvas_height ) ; graphics.setColor( 0, 0, 0 ) ; // black graphics.drawString( "" + current_day_of_week + " " + current_month + " " + current_day + ", " + current_year, 2, 0, Graphics.TOP | Graphics.LEFT ) ; // The following statements ensure that leading zeroes // precede single-digit minutes and seconds. String minutes_string = "00" + current_minutes ; minutes_string = minutes_string.substring( minutes_string.length() - 2, minutes_string.length() ) ; String seconds_string = "00" + current_seconds ; seconds_string = seconds_string.substring( seconds_string.length() - 2, seconds_string.length() ) ; graphics.drawString( current_hours + ":" + minutes_string + ":" + seconds_string, 2, 18, Graphics.TOP | Graphics.LEFT ) ; // Let's print an 8-point dot in the center of the clock. graphics.fillArc( clock_center_point_x - 4, clock_center_point_y - 4, 8, 8, 0, 360 ) ; // The following loop prints dots on the clock circle. int dot_index = 0 ; while ( dot_index < 60 ) { // The diameter of the clock face is 200. double dot_angle = dot_index * Math.PI / 30 - Math.PI / 2 ; int dot_position_x = (int) (Math.cos( dot_angle ) * 100 + clock_center_point_x ) ; int dot_position_y = (int) (Math.sin( dot_angle ) * 100 + clock_center_point_y ) ; int dot_diameter = 4 ; if ( ( dot_index % 5 ) == 0 ) { // Every 5th dot on the clock circle is a larger dot. dot_diameter = 6 ; } graphics.fillArc( dot_position_x - dot_diameter / 2, dot_position_y - dot_diameter / 2, dot_diameter, dot_diameter, 0, 360 ) ; dot_index = dot_index + 1 ; } // For every hand of the clock, we'll first calculte the // angle of the hand in question. Then we can calculate the // the coordinates of the end point of the hand, and finally // we'll draw the hand. double hour_hand_angle = ( current_hours * 30 + current_minutes / 2 ) * Math.PI / 180 - Math.PI /2 ; // 76 is the length of the hour hand int hour_hand_end_x = (int) (Math.cos( hour_hand_angle ) * 76 + clock_center_point_x ) ; int hour_hand_end_y = (int) (Math.sin( hour_hand_angle ) * 76 + clock_center_point_y ) ; graphics.drawLine( clock_center_point_x, clock_center_point_y, hour_hand_end_x, hour_hand_end_y ) ; double minute_hand_angle = ( (double) current_minutes + (double) current_seconds / 60.0 ) * Math.PI / 30 - Math.PI /2 ; // Minute hand length is 94. int minute_hand_end_x = (int) (Math.cos( minute_hand_angle ) * 94 + clock_center_point_x ) ; int minute_hand_end_y = (int) (Math.sin( minute_hand_angle ) * 94 + clock_center_point_y ) ; graphics.drawLine( clock_center_point_x, clock_center_point_y, minute_hand_end_x, minute_hand_end_y ) ; graphics.setColor( 255, 0, 0 ) ; // red double seconds_hand_angle = ((double) current_seconds + (double) current_milliseconds / 1000.0 ) * Math.PI / 30 - Math.PI /2 ; // 100 is the length of the seconds hand int seconds_hand_end_x = (int) (Math.cos( seconds_hand_angle ) * 100 + clock_center_point_x ) ; int seconds_hand_end_y = (int) (Math.sin( seconds_hand_angle) * 100 + clock_center_point_y ) ; graphics.drawLine( clock_center_point_x, clock_center_point_y, seconds_hand_end_x, seconds_hand_end_y ) ; } } public class ClockMIDlet extends MIDlet implements CommandListener { Display display_of_this_midlet = Display.getDisplay( this ) ; ClockCanvas clock_canvas = new ClockCanvas() ; Command exit_command = new Command( "Exit Clock", Command.EXIT, 1 ) ; protected void startApp() throws MIDletStateChangeException { display_of_this_midlet.setCurrent( clock_canvas ) ; clock_canvas.start_animation_thread() ; clock_canvas.addCommand( exit_command ) ; clock_canvas.setCommandListener( this ) ; } protected void pauseApp() { clock_canvas.stop_animation_thread() ; } protected void destroyApp( boolean unconditional_destruction_requested ) { clock_canvas.stop_animation_thread() ; } public void commandAction( Command given_command, Displayable display_content ) { if ( given_command == exit_command ) { destroyApp( false ) ; notifyDestroyed() ; } } }