| the complete webmaster | ||||
| tutorials | reviews | reference | ||
|
ClocksIntroductionEver think of creating a clock of your own style? Java has provided you enough tools to make your life easier. Beyond standard clock functions, they can be used in a variety of ways. For example, use them as timing devices for scheduled jobs, i.e. telling the system when to do what. Imagine this: you used to read the news at CNN's website 8:00 in the morning. What if your clock automatically opens that URL for you at that specific time? Isn't that just great? Besides, understanding the clock code in Java is far from difficult. To make it even simpler, two examples are provided here and explained in detail. Hopefully, you can get the hang of it in no time. I am going to walk through the codes of the two styles of clocks - digital and analog. After you understand how they work, you should be able to create your own version of clocks. Some similar clock references can be found at lots of websites. Check out Java Review Service (www.jars.com), Developer's Daily (www.devdaily.com), etc. All the demo files are downloadable: dc.html, dc.java, dc.class, ac.html, ac.java, and ac.class. BasicsI have mentioned double buffering a few times but would like to reiterate its importance in animation here. Double buffering is used to prepare a duplicate off-screen graphics object, which mainly shows the change from the previous frame and is drawn only when it is completely ready. This is done in order to reduce screen flickering caused by drawing and displaying at the same time. Also, in the analog clock I will present below, in order to decide the x coordinate for a point on a circle, it is simply radius times cosine plus the translation from the circle center. Similarly for y. If you don't know what in the world I am talking about. Don't worry. Let's just leave it at that for now. :-)A Digital ClockThe source code of the digital clock is listed in Fig 1 and its corresponding HTML is in Fig 2. Lines 1 - 3 import classes from JDK. Line 7 is for the offscreen graphics and Line 8 is for the offscreen image. Line 9 is for the thread control. Line 10 is for the panel size and animation delay. Line 12 is for the time object containing all info. Line 13 is for the time string. timewidth, timeheight, and timedescent are for the font used to display time. timeH, timeM, and timeS are used to store hour, minute, and second respectively. Lines 19 - 21 are to set up the panel size. Line 23 creates an object for offscreen image. Line 24 creates an object for offscreen graphics. In start(), we start a new thread if no thread is running. In stop(), we stop a running thread. We control the refreshing speed by delay in lines 44 - 58. Lines 61 - 64 override the default update() method. Lines 68 - 71 draw the background and set up font and color. Lines 72 - 75 retrieve the current time and store it into variables. Lines 76 - 88 construct the time string. Lines 90 - 97 get the font measures and draw the time string and its shadow. Line 99 refreshes the screen with the offscreen image.
001 import java.awt.*;
002 import java.applet.*;
003 import java.util.Date;
004
005 public class dc extends Applet implements Runnable
006 {
007 Graphics og;
008 Image oi;
009 Thread t = null;
010 int width, height, delay = 500;
011
012 Date currTime;
013 String time;
014 int timewidth, timeheight, timedescent, timeH, timeM, timeS;
015
016 public void init()
017 {
018 super.init();
019 width = size().width;
020 height = size().height;
021 resize(width, height);
022
023 oi = createImage(width, height);
024 og = oi.getGraphics();
025 }
026
027 public void start()
028 {
029 if (t == null)
030 {
031 t = new Thread(this);
032 t.start();
033 }
034 }
035
036 public void stop()
037 {
038 t.stop();
039 t = null;
040 }
041
042 public void run()
043 {
044 Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1);
045 while (true)
046 {
047 repaint();
048 try
049 {
050 Thread.sleep(delay);
056 }
057 catch (InterruptedException e) {}
058 }
059 }
060
061 public void update(Graphics g)
062 {
063 paint(g);
064 }
065
066 public void paint(Graphics g)
067 {
068 og.setColor(new Color(170, 170, 170));
069 og.fillRect(0, 0, width, height);
070 og.setFont(new Font("Helvetica", Font.BOLD, 15));
071 og.setColor(new Color(20, 20, 20));
072 currTime = new Date();
073 timeH = currTime.getHours();
074 timeM = currTime.getMinutes();
075 timeS = currTime.getSeconds();
076 time = "";
077 if (timeH < 10)
078 time = "0" + timeH;
079 else
080 time = "" + timeH;
081 if (timeM < 10)
082 time += ":0" + timeM;
083 else
084 time += ":" + timeM;
085 if (timeS < 10)
086 time += ":0" + timeS;
087 else
088 time += ":" + timeS;
089
090 timewidth = (og.getFontMetrics()).stringWidth(time);
091 timeheight = (og.getFontMetrics()).getHeight();
092 timedescent = (og.getFontMetrics()).getDescent();
093 og.drawString(time, (width - timewidth) / 2, height -
094 (height - timeheight) / 2 - timedescent);
095 og.setColor(new Color(230, 230, 230));
096 og.drawString(time, (width - timewidth) / 2 - 1, height -
097 (height - timeheight) / 2 - timedescent - 1);
098
099 g.drawImage(oi, 0, 0, this);
100 }
101 }
Fig 1: source code for the digital clock < applet code=scroller.class width=70 height=30> </applet> Fig 2: HTML example for the digital clock An Analog ClockThe source code of the analog clock is listed in Fig 3 and its corresponding HTML is in Fig 4. Lines 1 - 3 import classes from JDK. Line 7 is for the offscreen graphics and Line 8 is for the offscreen image. Line 9 is for the thread control. Line 10 is for the panel size and animation delay. Line 12 is for the time object containing all info. In line 13, timeH, timeM, and timeS are used to store hour, minute, and second respectively. radius is for the actual clock size. cx and cy are clock center coordinates. lenH, lenM, and lenS are lengths of the displaying hands. Lines 19 - 21 are to set up the panel size. Lines 23 - 28 are used to set up lengths of the hands and clock center. Line 30 creates an object for offscreen image. Line 31 creates an object for offscreen graphics. In start(), we start a new thread if no thread is running. In stop(), we stop a running thread. We control the refreshing speed by delay in lines 51 - 60. Lines 63 - 66 override the default update() method. Lines 70 - 71 draw the background. Lines 72 - 75 retrieve the current time and store it into variables. Lines 77 - 78 corrects the time to 12-hour mode. Lines 80 - 98 draw the 12 number markers and their shadows. Lines 99 - 106 draw the hour hand and its shadow. Lines 108 - 113 draw the minute hand and its shadow. Lines 115 - 120 draw the second hand and its shadow. Lines 122 - 127 draw the clock boundary and its shadow. Line 129 refreshes the screen with the offscreen image.
001 import java.awt.*;
002 import java.applet.*;
003 import java.util.Date;
004
005 public class ac extends Applet implements Runnable
006 {
007 Graphics og;
008 Image oi;
009 Thread t = null;
010 int width, height, delay = 500;
011
012 Date currTime;
013 int timeH, timeM, timeS, radius = 50, lenH, lenM, lenS,
014 lenIn, cx, cy, x1, y1, x2, y2;
015
016 public void init()
017 {
018 super.init();
019 width = size().width;
020 height = size().height;
021 resize(width, height);
022
023 lenH = 5 * radius / 10;
024 lenM = 6 * radius / 10;
025 lenS = 7 * radius / 10;
026 lenIn = 8 * radius / 10;
027 cx = width / 2;
028 cy = height / 2;
029
030 oi = createImage(width, height);
031 og = oi.getGraphics();
032 }
033
034 public void start()
035 {
036 if (t == null)
037 {
038 t = new Thread(this);
039 t.start();
040 }
041 }
042
043 public void stop()
044 {
045 t.stop();
046 t = null;
047 }
048
049 public void run()
050 {
051 Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1);
052 while (true)
053 {
054 repaint();
055 try
056 {
057 Thread.sleep(delay);
058 }
059 catch (InterruptedException e) {}
060 }
061 }
062
063 public void update(Graphics g)
064 {
065 paint(g);
066 }
067
068 public void paint(Graphics g)
069 {
070 og.setColor(new Color(170, 170, 170));
071 og.fillRect(0, 0, width, height);
072 currTime = new Date();
073 timeH = currTime.getHours();
074 timeM = currTime.getMinutes();
075 timeS = currTime.getSeconds();
076
077 if (timeH >= 12)
078 timeH -= 12;
079
080 for (int i = 1; i < 13; i++)
081 {
082 og.setColor(new Color(20, 20, 20));
083 x2 = (int)(cx + radius * Math.sin(i * 2 * 3.14159f / 12));
084 y2 = (int)(cy - radius * Math.cos(i * 2 * 3.14159f / 12));
085 if (i % 3 != 0)
086 {
087 x1 = (int)(cx + 0.9f * radius * Math.sin(i * 2 * 3.14159f / 12));
088 y1 = (int)(cy - 0.9f * radius * Math.cos(i * 2 * 3.14159f / 12));
089 }
090 else
091 {
092 x1 = (int)(cx + 0.8f * radius * Math.sin(i * 2 * 3.14159f / 12));
093 y1 = (int)(cy - 0.8f * radius * Math.cos(i * 2 * 3.14159f / 12));
094 }
095 og.drawLine(x1, y1, x2, y2);
096 og.setColor(new Color(230, 230, 230));
097 og.drawLine(x1 - 1, y1 - 1, x2 - 1, y2 - 1);
098 }
099 og.setColor(new Color(20, 20, 20));
100 x2 = (int)(cx + lenH * Math.sin((timeH + timeM / 60.0f + timeS / 3600.0f)
101 * 2 * 3.14159f / 12));
102 y2 = (int)(cy - lenH * Math.cos((timeH + timeM / 60.0f + timeS / 3600.0f)
103 * 2 * 3.14159f / 12));
104 og.drawLine(cx, cy, x2, y2);
105 og.setColor(Color.red);
106 og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1);
107
108 og.setColor(new Color(20, 20, 20));
109 x2 = (int)(cx + lenM * Math.sin((timeM + timeS / 60.0f) * 2 * 3.14159f / 60));
110 y2 = (int)(cy - lenM * Math.cos((timeM + timeS / 60.0f) * 2 * 3.14159f / 60));
111 og.drawLine(cx, cy, x2, y2);
112 og.setColor(Color.green);
113 og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1);
114
115 og.setColor(new Color(20, 20, 20));
116 x2 = (int)(cx + lenS * Math.sin(timeS * 2 * 3.14159f / 60));
117 y2 = (int)(cy - lenS * Math.cos(timeS * 2 * 3.14159f / 60));
118 og.drawLine(cx, cy, x2, y2);
119 og.setColor(Color.blue);
120 og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1);
121
122 og.setColor(new Color(20, 20, 20));
123 og.drawOval((width - 2 * radius) / 2, (height - 2 * radius) / 2, 2 * radius,
124 2 * radius);
125 og.setColor(new Color(230, 230, 230));
126 og.drawOval((width - 2 * radius) / 2 - 1, (height - 2 * radius) / 2 - 1,
127 2 * radius, 2 * radius);
128
129 g.drawImage(oi, 0, 0, this);
130 }
131 }
Fig 3: source code for the analog clock < applet code=ac.class width=120 height=120> </applet> Fig 4: HTML example for the analog clock ConclusionThe codes for two styles of clocks are explained what-I-believe-to-be in sufficient detail in this article - digital and analog. As I mentioned at the beginning of this article, there are some functionalities beyond clocks' normal usage, e.g. scheduled work. With a deeper understanding of how clocks work, you should be able to create your own artistic clocks and incorporate some jobs that can be tied to a timing device. I hope this article can inspire you in that sense. I will talk about more common dynamic features that are widely seen on the web in the coming series. NEXT: Menus: Part I
Author: Chunyen Liu
More articles about Java |
| write for us | about us | advertise |
Copyright 1997, 1998 A Big Lime. All rights reserved.