0

I'm making a clock applet, and I'm almost done, but there's still one thing I need to do. I want to make the clock "tick" every time the second hand moves, but I can't figure out where to put the code for the *tick* sound. Here is the code for the applet:

import java.applet.*;
import java.awt.*;
import java.util.*;
import java.net.URL;
import java.text.*;

public class ClockApplet extends Applet implements Runnable {
    Ellipse2D line1 = new Ellipse2D.Float(100, 150, 200, 200);

    int width, height;
    Thread t = null;
    boolean threadSuspended;
    int hours = 0, minutes = 0, seconds = 0;
    String timeString = "";

    public void init() {
        width = getSize().width;
        height = getSize().height;
        setBackground(Color.white);
    }

    public void start() {
        if (t == null) {
            t = new Thread(this);
            t.setPriority(Thread.MIN_PRIORITY);
            threadSuspended = false;
            t.start();
        } else {
            if (threadSuspended) {
                threadSuspended = false;
                synchronized (this) {
                    notify();
                }
            }
        }
    }

    public void stop() {
        threadSuspended = true;
    }

    public void run() {
        try {
            while (true) {

                // Here's where the thread does some work:

                Calendar cal = Calendar.getInstance();
                hours = cal.get(Calendar.HOUR_OF_DAY);
                if (hours > 12)
                    hours -= 12;
                minutes = cal.get(Calendar.MINUTE);
                seconds = cal.get(Calendar.SECOND);

                SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss",
                        Locale.getDefault());
                Date date = cal.getTime();
                timeString = formatter.format(date);

                // Now the thread checks to see if it should suspend itself
                if (threadSuspended) {
                    synchronized (this) {
                        while (threadSuspended) {
                            wait();
                        }
                    }
                }
                repaint();

                t.sleep(1000); // interval given in milliseconds

            }
        } catch (InterruptedException e) {
        }
    }

    void drawHand(double angle, int radius, Graphics g) {
        angle -= 0.5 * Math.PI;
        int x = (int) (radius * Math.cos(angle));
        int y = (int) (radius * Math.sin(angle));
        g.drawLine(width / 2, height / 2, width / 2 + x, height / 2 + y);
    }

    void drawWedge(double angle, int radius, Graphics g) {
        angle -= 0.5 * Math.PI;
        int x = (int) (radius * Math.cos(angle));
        int y = (int) (radius * Math.sin(angle));
        angle += 2 * Math.PI / 3;
        int x2 = (int) (5 * Math.cos(angle));
        int y2 = (int) (5 * Math.sin(angle));
        angle += 2 * Math.PI / 3;
        int x3 = (int) (5 * Math.cos(angle));
        int y3 = (int) (5 * Math.sin(angle));
        g.drawLine(width / 2 + x2, height / 2 + y2, width / 2 + x, height / 2
                + y);
        g.drawLine(width / 2 + x3, height / 2 + y3, width / 2 + x, height / 2
                + y);
        g.drawLine(width / 2 + x2, height / 2 + y2, width / 2 + x3, height / 2
                + y3);
    }

    void drawCircle(Graphics g) {
        g.drawOval(0, 0, 200, 200);
    }

    public void paint(Graphics g) {
        g.setColor(Color.black);
        drawWedge(2 * Math.PI * hours / 12, width / 5, g);
        drawWedge(2 * Math.PI * minutes / 60, width / 3, g);
        g.setColor(Color.red);
        drawHand(2 * Math.PI * seconds / 60, width / 2, g);
        g.setColor(Color.black);
        g.drawString(timeString + " ET", 10, height - 10);
        g.setFont(new Font("Arial", Font.PLAIN, 30));
        g.drawString("12", 85, 30);
        g.drawString("1", 140, 40);
        g.drawString("2", 170, 70);
        g.drawString("3", 180, 110);
        g.drawString("4", 170, 150);
        g.drawString("5", 140, 180);
        g.drawString("6", 92, 195);
        g.drawString("7", 46, 180);
        g.drawString("8", 16, 150);
        g.drawString("9", 5, 110);
        g.drawString("10", 16, 70);
        g.drawString("11", 46, 40);
        drawCircle(g);
    }

}

And here is the code for the *tick* sound:

try {
    Clip tick = AudioSystem.getClip();
    URL clipURL = new URL("file://C:/users/owner/desktop/Tick.wav");
    AudioInputStream ais = AudioSystem.getAudioInputStream(clipURL);
    tick.open(ais);
    tick.start();
} catch (Exception e) {
    System.out.println("Error playing sound!");
    }

All I need to know is where to put the sound code into the applet code. I've tried various places, but none seem to work.

livefree75
  • 720
  • 8
  • 18
  • 1
    *"I've tried various places, but none seem to work."* Programming is not magic, bit I suspect the `t.sleep(1000);` is complicating matters. But first some other matters.. – Andrew Thompson May 15 '13 at 16:41
  • 1) Why code an applet? If it is due due to spec. by teacher, please refer them to [Why CS teachers should stop teaching Java applets](http://programmers.blogoverflow.com/2013/05/why-cs-teachers-should-stop-teaching-java-applets/). 2) Why AWT rather than Swing? See this answer on [Swing extras over AWT](http://stackoverflow.com/a/6255978/418556) for many good reasons to abandon using AWT components. If you need to support older AWT based APIs, see [Mixing Heavyweight and Lightweight Components](http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html). – Andrew Thompson May 15 '13 at 16:41
  • What I actually did was I got most of the code from another source, but that code was just some hands going around the clock. Now the clock has numbers, the second hand is red, and there is a circle around it, just like a regular clock. I just need to know how to make it tick. – livefree75 May 16 '13 at 11:50
  • *"I just need to know how to make it tick."* I have no intention of wasting time helping on an AWT based applet. Transfer to Swing & a `JFrame` based application & we can progress this. Otherwise.. – Andrew Thompson May 16 '13 at 14:17

1 Answers1

0

This answer applies to JApplets or Applications. (I've not used Applets, myself.)

(1) I would make the tick Clip an instance variable that is loaded when the top level class is instantiated. In the context of a JApplet, that would be during the init() method. I the context of an application, that might be via making the clock graphic display a JComponent or JPanel, and instantiating the Clip when instantiating the container for the graphic.

(It doesn't make sense to repeatedly load the Clip into memory! The point of a Clip is to do it once and then reset it when you wish to reuse it. A Clip that is repeatedly loaded takes LONGER to start playing than a SourceDataLine, as the entire sound file has to be loaded before playing will initiate.)

(2) I would create a new thread to run the tick Clip by resetting the position to the start of the Clip (frame 0) and then playing it.

(3) I would launch this thread repeatedly from the while loop where the graphic is redrawn. Presumably the thread would die as soon as it finishes executing. There might be bugginess if the click sound is longer than a second.

I'm not saying that this is for sure "correct". It might make sense to launch both the update of the graphic and the sound thread via a util.Timer set to a 1000msec interval.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41