Part 7. Advanced GUI Programming

 
[Page 782]

24.7. (Optional) Case Study: Clock with Audio

The example creates an applet that displays a running clock and announces the time at one-minute intervals. For example, if the current time is 6:30:00, the applet announces, "six o'clock thirty minutes A.M ." If the current time is 20:20:00, the applet announces, "eight o'clock twenty minutes P.M ." Also add a label to display the digital time, as shown in Figure 24.7.

Figure 24.7. The applet displays a clock and announces the time every minute.


To announce the time, the applet plays three audio clips . The first clip announces the hour , the second announces the minute, and the third announces AM or PM. All of the audio files are stored in the directory audio , a subdirectory of the applet's class directory. The twelve audio files that are used to announce the hours are stored in the files hour0.au , hour1.au , and so on, to hour11.au . The sixty audio files that are used to announce the minutes are stored in the files minute0.au , minute1.au , and so on, to minute59.au . The two audio files that are used to announce AM or PM are stored in the file am.au and pm.au .

You need to play three audio clips on a separate thread to avoid animation delays. To illustrate the problem, let us first write a program without playing the audio on a separate thread.

In §13.12, the StillClock class was developed to draw a still clock to show the current time. Create an applet named ClockWithAudio (Listing 24.4) that contains an instance of StillClock to display an analog clock, and an instance of JLabel to display the digit time. Override the init method to load the audio files. Use a Timer object to set and display the current time continuously at a fixed rate. When the second is zero, announce the current time.

Listing 24.4. ClockWithAudio.java
(This item is displayed on pages 782 - 784 in the print version)
 1   import   java.applet.*; 2   import   javax.swing.*; 3   import   java.awt.event.*; 4   import   java.awt.*; 5 6   public class    ClockWithAudio   extends   JApplet  { 7    protected   AudioClip[] hourAudio =   new   AudioClip[   12   ];  8    protected   AudioClip[] minuteAudio =   new   AudioClip[   60   ];  9 10  // Create audio clips for pronouncing am and pm  11   protected   AudioClip  amAudio  = 12  Applet.newAudioClip(   this   .getClass().getResource(   "audio/am.au"   ));  13   protected   AudioClip  pmAudio  = 14 Applet.newAudioClip(   this   .getClass().getResource(  "     audio/pm.au     "  )); 15 16  // Create a clock  17   private   StillClock clock =   new   StillClock(); 18 19  // Create a timer  20  private Timer timer =   new   Timer(   1000   ,   new   TimerListener());  21 

[Page 783]
 22  // Create a label to display time  23    private   JLabel jlblDigitTime =   new   JLabel(   ""   , JLabel.CENTER);  24 25  /** Initialize the applet */  26   public void   init() { 27  // Create audio clips for pronouncing hours  28   for   (   int   i =     ; i <   12   ; i++) 29 hourAudio[i] = Applet.newAudioClip( 30   this   .getClass().getResource(    "audio/hour"   + i +   ".au"    )); 31 32  // Create audio clips for pronouncing minutes  33   for   (   int   i =     ; i <   60   ; i++) 34 minuteAudio[i] = Applet.newAudioClip( 35   this   .getClass().getResource(    "audio/minute"   + i +   ".au"    )); 36 37  // Add clock and time label to the content pane of the applet  38 add(clock, BorderLayout.CENTER); 39 add(jlblDigitTime, BorderLayout.SOUTH); 40 } 41 42  /** Override the applet's start method */  43   public void   start() { 44  timer.start();  // Resume clock   45 } 46 47  /** Override the applet's stop method */  48   public void   stop() { 49  timer.stop();  // Suspend clock   50 } 51 52    private   class TimerListener   implements   ActionListener {  53   public void   actionPerformed(ActionEvent e) { 54  clock.setCurrentTime();  55  clock.repaint();  56 jlblDigitTime.setText(clock.getHour() +   ":"   + clock.getMinute() 57 +   ":"   + clock.getSecond()); 58   if   (clock.getSecond() ==     ) 59  announceTime(clock.getHour(), clock.getMinute());  60 } 61 } 62 63  /** Announce the current time at every minute */  64   public void   announceTime(   int   hour,   int   minute) { 65  // Announce hour  66  hourAudio[hour %   12   ].play();  67 68   try   { 69  // Time delay to allow hourAudio play to finish  70 Thread.sleep(   1500   ); 71 72  // Announce minute  73  minuteAudio[minute].play();  74 75  // Time delay to allow minuteAudio play to finish  76 Thread.sleep(   1500   ); 77 } 78   catch   (InterruptedException ex) { 79 } 80 81  // Announce am or pm  82   if   (hour <   12   ) 

[Page 784]
 83  amAudio.play();  84   else   85  pmAudio.play();  86 } 87 } 

The hourAudio is an array of twelve audio clips that are used to announce the twelve hours of the day (line 7); the minuteAudio is an audio clip that is used to announce the minutes in an hour (line 8). The amAudio announces A.M . (line 11); the pmAudio announces P.M . (line 13).

The init() method creates hour audio clips (lines 29 “30) and minute audio clips (lines 34 “35), and places a clock and a label in the applet (lines 38 “39).

An ActionEvent is fired by the timer every second. In the listener's actionPerformed method (lines 53 “60), the clock is repainted with the new current time, and the digital time is displayed in the label.

In the announceTime method (lines 64 “86), the sleep() method (lines 70, 76) is purposely invoked to ensure that one clip finishes before the next clip starts, so that the clips do not interfere with each other.

The applet's start() and stop() methods (lines 43 “50) are overridden to ensure that the timer starts or stops when the applet is restarted or stopped .

When you run the preceding program, you will notice that the second hand does not display at the first, second, and third seconds of the minute. This is because sleep(1500) is invoked twice in the announceTime() method, which takes three seconds to announce the time at the beginning of each minute. Thus, the next action event is delayed for three seconds during the first three seconds of each minute. As a result of this delay, the time is not updated and the clock was not repainted for these three seconds. To fix this problem, you should announce the time on a separate thread. This can be accomplished by modifying the announceTime method. Listing 24.5 gives the new program.

Listing 24.5. ClockWithAudioOnSeparateThread.java
(This item is displayed on pages 784 - 785 in the print version)
 1  // same import statements as in Listing 24.4, so omitted  2 3   public class   ClockWithAudioOnSeparateThread   extends   JApplet { 4  // same as in lines 7-61, so omitted  5 6  /** Announce the current time at every minute */  7   public void   announceTime(   int   h,   int   m) { 8    new   Thread(   new   AnnounceTimeOnSeparateThread(h, m)).start();  9 } 10 11  /** Inner class for announcing time */  12    class   AnnounceTimeOnSeparateThread   implements   Runnable  { 13   private int   hour, minute; 14 15  /** Get Audio clips */  16   public   AnnounceTimeOnSeparateThread(   int   hour,   int   minute) { 17   this   .hour = hour; 18   this   .minute = minute; 19 } 20 21    public void   run()  { 22  // Announce hour  23 hourAudio[hour %   12   ].play(); 24 25   try   { 26  // Time delay to allow hourAudio play to finish  27 Thread.sleep(   1500   ); 28 

[Page 785]
 29  // Announce minute  30 minuteAudio[minute].play(); 31 32  // Time delay to allow minuteAudio play to finish  33 Thread.sleep(   1500   ); 34 } 35   catch   (InterruptedException ex) { 36 } 37 38  // Announce am or pm  39   if   (hour <   12   ) 40 amAudio.play(); 41   else   42 pmAudio.play(); 43 } 44 } 45 } 

The new class ClockWithAudioOnSeparateThread is the same as ClockWithAudio except that the announceTime method is new. The new announceTime method creates a thread (line 8) for the task of announcing time. The task class is declared an inner class (lines 12 “44). The run method (line 21) announces the time on a separate thread.

When running this program, you will discover that the audio does not interfere with the clock animation because an instance of AnnounceTimeOnSeparateThread starts on a separate thread to announce the current time. This thread is independent of the thread on which the actionPerformed method runs.

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net