Analog stopwatch using Python turtle module

In this tutorial, let’s build an analog stopwatch using Python’s turtle module. Let us have a circular representation of hours, minutes and seconds as distance traversed by the respective turtles.

Turtle movement calculations:

• The seconds hand of an analog clock traverses 6 degrees every second
• The minute hand traverses 6 degrees every minute; 1 min = 60 seconds -> therefore minute hand traverses 6/60 degrees every second.
• The hour hand traverses 30 degrees every hour; 1 hour = 3600 seconds -> therefore hour hand traverses 30/3600 degrees every second

Using these traversal calculations we create  3 turtles and move them every second after a fixed delay. This delay plus the time taken to traverse all the three triangle’s each time must be equal to 1000 milliseconds to ensure that it takes 1 second in all for each tick.

We need to import turtle,time, keyboard and math modules.

Here on running the script, stop watch begins immediately. The clock can be paused in between and resumed after sometime or the stop watch can be stopped altogether as per the user’s requirements.

Here we  are using “KeyboardInterrupt”  from keyboard module to pause/resume and to stop the timer. The user can press “ctrl+c” to interrupt the stop watch (try block) and as a result pause the timer. After generating keyboard interrupt by pressing ctrl+c press “space” to resume the stop watch or press “esc” to stop the stopwatch completely.

Note: This script must be run in the terminal as often IDE’s have “ctrl+c” command as the shortcut for copying text.

Code:

```import turtle  # import turtle for graphical representation of analog stop watch clock import time
import time  # importing time to measure time and track duration
import keyboard  # to use keyboard interrupt
import math

print("""
To pause the stopwatch kindly press ctrl+c.\n
To resume the stop watch press "space" to resume the stop watch or press "esc" if you wish to stop the stopwatch\n
Stop watch begins!\n
""")

second_extent = 6  # second hand traverses 6 degrees every second in a clock
minute_extent = 6 / 60  # minute hand traverses 6 degrees every minute so it traverses 6/60 degrees every second
hour_extent = 30 / 3600  # hour hand traverses 30 degrees every hour so it traverses 30/3600 degrees every second

second_turtle = turtle.Turtle()  # creating a turtle that represents seconds traversed
minute_turtle = turtle.Turtle()  # creating a turtle that represents minutes traversed
hour_turtle = turtle.Turtle()  # creating a turtle that represents hours traversed

window = turtle.Screen()
window.bgcolor("#F5F0E1")  # Half white background of turtle screen
window.setup(400, 400)  # changing turtle window size for aesthetics of the window

def circle_draw():  # function to move turtles every
second_turtle.circle(-100,
extent=second_extent)  # note: radius is negative to move the turtles in clockwise direction
minute_turtle.circle(-120, extent=minute_extent)
hour_turtle.circle(-140, extent=hour_extent)

def turtle_settings():
# turtle speeds
second_turtle.speed(0)
minute_turtle.speed(0)
hour_turtle.speed(0)

# turtle colors
second_turtle.color("#1E3D59")  # blue
minute_turtle.color("#FF6E40")  # orange
hour_turtle.color("#FFC13B")  # yellow

# turtle pen sizes/ stroke sizes
hour_turtle.pensize(4)
minute_turtle.pensize(3)
second_turtle.pensize(2)

# second hand turtles starting position
second_turtle.penup()
second_turtle.goto(0, 100)
second_turtle.pendown()

# minute hand turtles starting location
minute_turtle.penup()
minute_turtle.goto(0, 120)
minute_turtle.pendown()

# hour hands starting location
hour_turtle.penup()
hour_turtle.goto(0, 140)
hour_turtle.pendown()

def turtle_reset():
second_turtle.reset()
minute_turtle.reset()
hour_turtle.reset()

def time_conversion(time_elapsed):
# converting seconds to hours:minutes:seconds format
hour = math.floor(time_elapsed / 3600)
minute = math.floor((time_elapsed % 3600) / 60)
second = round((time_elapsed % 3600) % 60)
print(f'Time elapsed: {hour}:{minute}:{second}\n')

turtle_settings()  # setting up the turtles with customisation and positions
calibration_start = time.time()  # here determining the time required to move a the three turtles every sec
circle_draw()
calibration_end = time.time()
draw_time = (calibration_end - calibration_start)  # calculating time taken to move the three turtles
# print(draw_time)   uncomment and clear this comment to see the time required to move the three turtles each time in milliseconds
turtle_reset()  # calling turtle reset to clear the drawings and turtle settings
turtle_settings()  # turtle settings to customise turtles and assign their positions

'''
delay between any two function calls of circle draw to ensure that that time gap between
any two calls and the time to taken to move the three turtles together makes 1000 milliseconds
'''
compensated_delay = int(1000 - round((1000 * draw_time), 3))  # subtracting drawing time to ensure timing accuracy
# print(compensated_delay) uncomment this line to see the compensated delay

elapsed_time = 0
start = time.time()
while True:
try:
turtle.ontimer(circle_draw(), compensated_delay)
# if the stop watch is interrupted by ctrl+c command then the except block of the code executes
except KeyboardInterrupt:
elapsed_time = elapsed_time + time.time() - start
time_conversion(elapsed_time)  # converting seconds to hours:minutes:seconds format
# to stop timer and halt program until the stopwatch is resumed or terminated again by pressing the respective key
status = keyboard.read_key()
if status == 'space':  # space to resume stop watch again
start = time.time()
elif status == 'esc':  # esc to stop the stop watch completely
print("Stop watch terminated")
break

window.bgcolor("#C6D7EB")  # changing background color of turtle window to indicate end of stopwatch
window.exitonclick()  # to prevent turtle screen from shutting down immediately after the stop watch stops
```

Output:

```C:\Users\User\PycharmProjects\CodeSpeedy>python analog_stopwatch.py

To pause the stopwatch kindly press "ctrl+c".

To resume the stop watch press "space" or press "esc" if you wish to stop the stopwatch

Stop watch begins!

Time elapsed: 0:19:59```

`Time elapsed: 0:20:57`

`Stop watch terminated`