// ClockWithDateApplet.java (c) 2006 Kari Laitinen // http://www.naturalprogramming.com/ // 2006-01-25 File created. // 2009-10-26 Last modification. // This is the Swing version of program ClockApplet.java // Actually, this program is in many ways different from the old // ClockApplet.java. // Date and Clock are displayed on different panels, each panel sharing // its own half of the applet area. // Both panels run a thread which makes them to update the screen. // A call to repaint() updates only the component for which the // repaint() was invoked. // For more information about class GregorianCalendar, see program // Showtime.java in javafiles3 folder. import java.awt.* ; import java.awt.geom.* ; // Classes Line2D, Ellipse2D, etc. import java.util.* ; import javax.swing.* ; class DatePanel extends JPanel implements Runnable { Thread thread_to_run_date_updating ; boolean thread_must_be_executed ; public void start_animation_thread() { if ( thread_to_run_date_updating == null ) { thread_must_be_executed = true ; thread_to_run_date_updating = new Thread( this ) ; thread_to_run_date_updating.start() ; } } public void stop_animation_thread() { if ( thread_to_run_date_updating != null ) { thread_to_run_date_updating.interrupt() ; thread_must_be_executed = false ; thread_to_run_date_updating = null ; } } // The date is updated once a minute. public void run() { while ( thread_must_be_executed == true ) { repaint() ; try { Thread.sleep( 60000 ) ; // Suspend for 60 seconds. } catch ( InterruptedException caught_exception ) { // No actions to handle the exception. } } } public void paintComponent( Graphics graphics ) { super.paintComponent( graphics ) ; Graphics2D graphics2D = (Graphics2D) graphics ; String[] days_of_week = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } ; String[] names_of_months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } ; Calendar time_now = new GregorianCalendar() ; 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 ] ; // The following statements print frames around the panel area. graphics2D.setStroke( new BasicStroke( 6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ) ; graphics2D.setPaint( Color.cyan ) ; graphics2D.draw( new Rectangle2D.Double( 3, 3, getWidth() - 6, getHeight() - 6 ) ) ; graphics2D.setPaint( Color.magenta ) ; graphics2D.draw( new Rectangle2D.Double( 9, 9, getWidth() - 18, getHeight() - 18 ) ) ; graphics2D.setStroke( new BasicStroke( 1 ) ) ; graphics2D.setPaint( Color.black ) ; graphics2D.draw( new Rectangle2D.Double( 0, 0, getWidth() - 1, getHeight() - 1 ) ) ; // And finally we print the date information. We'll select the // font according to the width of the panel on which we draw. if ( getWidth() > 350 ) { graphics.setFont( new Font( "Monospaced", Font.BOLD, 28 ) ) ; } else { graphics.setFont( new Font( "Monospaced", Font.BOLD, 12 ) ) ; } graphics.drawString( current_month + " " + current_day + ", " + current_year, getWidth() / 10, getHeight() / 5 * 2 ) ; graphics.drawString( current_day_of_week, getWidth() / 10, getHeight() / 5 * 3 ) ; } } class Clock2DPanel extends JPanel implements Runnable { static final int HOUR_HAND_LENGTH = 152 ; static final int MINUTE_HAND_LENGTH = 188 ; static final int SECOND_HAND_LENGTH = 200 ; Thread thread_that_runs_the_clock ; boolean thread_must_be_executed ; public void start_animation_thread() { if ( thread_that_runs_the_clock == null ) { thread_must_be_executed = true ; thread_that_runs_the_clock = new Thread( this ) ; thread_that_runs_the_clock.start() ; } } public void stop_animation_thread() { if ( thread_that_runs_the_clock != null ) { thread_that_runs_the_clock.interrupt() ; thread_must_be_executed = false ; thread_that_runs_the_clock = null ; } } public void run() { while ( thread_must_be_executed == true ) { repaint() ; try { Thread.sleep( 200 ) ; // Suspend for 0.2 seconds. } catch ( InterruptedException caught_exception ) { // No actions to handle the exception. } } } public void paintComponent( Graphics graphics ) { super.paintComponent( graphics ) ; Graphics2D graphics2D = (Graphics2D) graphics ; Calendar time_now = new GregorianCalendar() ; 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.drawString( String.format( "%d:%02d:%02d", current_hours, current_minutes, current_seconds ), 20, 40 ); int clock_center_point_x = getWidth() / 2 ; int clock_center_point_y = getHeight() / 2 ; // The following loop prints dots on the clock dial. int dot_index = 0 ; while ( dot_index < 60 ) { double dot_angle = dot_index * Math.PI / 30 - Math.PI / 2 ; int dot_position_x = (int) (Math.cos( dot_angle ) * SECOND_HAND_LENGTH + clock_center_point_x ) ; int dot_position_y = (int) (Math.sin( dot_angle ) * SECOND_HAND_LENGTH + 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 = 8 ; } graphics.fillOval( dot_position_x - dot_diameter / 2, dot_position_y - dot_diameter / 2, dot_diameter, dot_diameter ) ; dot_index = dot_index + 1 ; } double hour_hand_angle = ( current_hours * 30 + current_minutes / 2 ) * Math.PI / 180 - Math.PI /2 ; int hour_hand_end_x = (int) ( Math.cos( hour_hand_angle ) * HOUR_HAND_LENGTH + clock_center_point_x ) ; int hour_hand_end_y = (int) ( Math.sin( hour_hand_angle ) * HOUR_HAND_LENGTH + clock_center_point_y ) ; Line2D.Double current_hour_hand = new Line2D.Double( 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 ; int minute_hand_end_x = (int) ( Math.cos( minute_hand_angle ) * MINUTE_HAND_LENGTH + clock_center_point_x ) ; int minute_hand_end_y = (int) ( Math.sin( minute_hand_angle ) * MINUTE_HAND_LENGTH + clock_center_point_y ) ; Line2D.Double current_minute_hand = new Line2D.Double ( clock_center_point_x, clock_center_point_y, minute_hand_end_x, minute_hand_end_y ) ; graphics2D.setStroke( new BasicStroke( 12, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ) ; // The following statement draws a black frame around the panel area. graphics2D.draw( new Rectangle2D.Double( 6, 6, getWidth() - 12, getHeight() - 12 ) ) ; // Let's draw the hour and minute hands as thick black lines. graphics2D.draw( current_hour_hand ) ; graphics2D.draw( current_minute_hand ) ; // Now we change color and line width to draw the 'phosphorous' // lines on the hour and minute hands. graphics2D.setPaint( Color.GREEN ) ; graphics2D.setStroke( new BasicStroke( 6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ) ; graphics2D.draw( current_hour_hand ) ; graphics2D.draw( current_minute_hand ) ; // Now, as the stroke width is 6, let's further // decorate the frame around the panel area. graphics2D.setPaint( Color.LIGHT_GRAY ) ; graphics2D.draw( new Rectangle2D.Double( 6, 6, getWidth() - 12, getHeight() - 12 ) ) ; // Let's print a 16-point dot into the center of the clock. graphics2D.setPaint( Color.BLACK ) ; graphics2D.fill( new Ellipse2D.Double( clock_center_point_x - 8, clock_center_point_y - 8, 16, 16 ) ) ; // And finally we'll draw the second hand. graphics2D.setStroke( new BasicStroke( 2 ) ) ; graphics2D.setPaint( Color.DARK_GRAY ) ; double second_hand_angle = ((double) current_seconds + (double) current_milliseconds / 1000.0 ) * Math.PI / 30 - Math.PI /2 ; int second_hand_end_x = (int) ( Math.cos( second_hand_angle ) * SECOND_HAND_LENGTH + clock_center_point_x ) ; int second_hand_end_y = (int) ( Math.sin( second_hand_angle) * SECOND_HAND_LENGTH + clock_center_point_y ) ; graphics2D.draw( new Line2D.Double( clock_center_point_x, clock_center_point_y, second_hand_end_x, second_hand_end_y ) ) ; } } public class ClockWithDateApplet extends JApplet { DatePanel panel_for_the_date ; Clock2DPanel panel_for_the_clock ; public void init() { Container content_pane_of_this_applet = getContentPane() ; content_pane_of_this_applet.setLayout( new GridLayout( 1, 2 ) ) ; panel_for_the_date = new DatePanel() ; panel_for_the_clock = new Clock2DPanel() ; content_pane_of_this_applet.add( panel_for_the_date ) ; content_pane_of_this_applet.add( panel_for_the_clock ) ; } public void start() { panel_for_the_date.start_animation_thread() ; panel_for_the_clock.start_animation_thread() ; } public void stop() { panel_for_the_date.stop_animation_thread() ; panel_for_the_clock.stop_animation_thread() ; } }