"""This module provides functionality for creating and updating both analog and
decimal clocks using the Tkinter GUI framework. It supports the display of time
in traditional 24-hour format as well as in decimal time (divided into
decidays, centidays, and seconds).
The clocks are drawn on a canvas with customizable styles for various components such as hands,
ticks, and backgrounds. The module uses a global `styles` dictionary to control colors, fonts,
and other visual aspects, ensuring a consistent look across the clocks.
Main Features:
---------------
- Analog clock with 24-hour format and decimal clock using the Swatch Internet Time system.
- Customizable clock hands (hour, minute, second, deciday, centiday) with different lengths and
colors.
- Digital time display below the clock with configurable font and color.
- Inner circular scale displaying ticks and numbers for both analog and decimal clocks.
- Real-time updates with smooth transitions using the `update_clock` function.
- Modular approach with helper functions to handle specific parts of the clock, such as drawing
hands, updating kiloseconds/decidays, and drawing the clock face.
Functions:
----------
- `update_clock`: Updates clock hands and digital time, switching between analog and decimal time.
- `draw_hand`: Draws a clock hand as a trapezoid with a triangular tip.
- `draw_inner_scale`: Draws an inner circular scale with ticks for time tracking.
- `draw_clock_face`: Draws the clock face, including tick marks and numbers.
- `update_kiloseconds`: Displays kiloseconds below the clock in the analog time format.
- `update_decidays`: Displays decidays below the clock in decimal time format.
- `run_clock`: Main function to initialize the Tkinter window and start both analog and decimal
clocks.
The module allows users to run a clock that displays time in either the traditional 24-hour format
or in a decimal-based time system, providing a visually appealing and functional experience.
Dependencies:
------------
- `math`: For trigonometric calculations used in drawing hands and clock ticks.
- `os`: Used for system-level operations (though not explicitly used in this module).
- `time`: For time-related functions and to retrieve the current system time.
- `tkinter`: For creating and updating the graphical user interface.
- `datetime`: For working with date and time, especially in retrieving the current time.
"""
import math
import tkinter as tk
from typing import Dict, List, NamedTuple, Optional, Tuple, TypedDict, Union
from utms.utils import get_seconds_since_midnight
[docs]
class CanvasConfig(NamedTuple):
"""Configuration for the canvas used to draw the clock.
Attributes:
canvas (tk.Canvas): The tkinter canvas object where the clock is drawn.
width (int): The width of the canvas in pixels.
height (int): The height of the canvas in pixels.
center (Tuple[int, int]): The coordinates of the canvas center as (x, y).
"""
canvas: tk.Canvas
width: int
height: int
center: Tuple[int, int]
[docs]
class HandConfig(NamedTuple):
"""Configuration for a clock hand.
Attributes:
length (float): The length of the clock hand in pixels.
angle (float): The angle of the clock hand in radians, relative to 12 o'clock.
base_width (int): The base width of the clock hand in pixels.
color (str): The color of the clock hand as a hexadecimal or color name.
tag (str): The tag used for grouping the clock hand in the canvas.
"""
length: float
angle: float
base_width: int
color: str
tag: str
[docs]
class Styles(TypedDict):
"""Configuration for the visual styles of the clock.
Attributes:
background_color (str): The background color of the clock as a hexadecimal or color name.
inner_color (str): The inner color of the clock face as a hexadecimal or color name.
frame_color (str): The color of the clock frame as a hexadecimal or color name.
center_circle_color (str): The color of the clock's center circle.
hand_colors (Dict[str, str]): A mapping of hand names ('hour', 'minute', etc.) to their
colors.
hand_widths (Dict[str, int]): A mapping of hand names to their widths in pixels.
tick_color (str): The color of the clock's tick marks.
outline_color (str): The color of the clock's outline.
digit_color (str): The color of the clock's digits.
font (Tuple[str, int]): The font and size used for the clock's digits.
digital_time_color (str): The color of the digital time display.
digital_font (Tuple[str, int]): The font and size used for the digital time display.
scale_tick_color (str): The color of the scale tick marks.
scale_digit_color (str): The color of the scale digits.
kilosecond_color (str): The color of the kilosecond hand.
deciday_color (str): The color of the deciday hand.
"""
background_color: str
inner_color: str
frame_color: str
center_circle_color: str
hand_colors: Dict[str, str]
hand_widths: Dict[str, int]
tick_color: str
outline_color: str
digit_color: str
font: Tuple[str, int]
digital_time_color: str
digital_font: Tuple[str, int]
scale_tick_color: str
scale_digit_color: str
kilosecond_color: str
deciday_color: str
styles: Styles = {
"background_color": "#B0B0B0",
"inner_color": "#E8E8E8",
"frame_color": "#636363",
"center_circle_color": "#636363",
"hand_colors": {
"hour": "#4A4A4A",
"minute": "#000000",
"second": "#FF3131",
"deciday": "#4A4A4A",
"centiday": "#000000",
},
"hand_widths": {
"hour": 4,
"minute": 2,
"second": 1,
"deciday": 4,
"centiday": 2,
},
"tick_color": "#636363",
"outline_color": "#000000",
"digit_color": "#000000",
"font": ("Orbitron", 16),
"digital_time_color": "#000000",
"digital_font": ("Orbitron", 16),
"scale_tick_color": "#636363",
"scale_digit_color": "#000000",
"kilosecond_color": "#000000",
"deciday_color": "#000000",
}
[docs]
def calculate_angles(
seconds_since_midnight: int, is_decimal: bool
) -> Tuple[float, float, float, Union[float, None], Union[float, None]]:
"""Calculates the angles of the clock hands based on whether it's decimal
time or not."""
if not is_decimal:
# Analog time (24-hour format)
hour = (seconds_since_midnight // 3600) % 24 # 24-hour format, not 12-hour
minute = (seconds_since_midnight // 60) % 60
second = seconds_since_midnight % 60
# Angles for hands
hour_angle = math.radians(
(360 / 12) * (hour % 12) + (360 / 12) * (minute / 60) + (360 / 12) * (second / 3600)
)
minute_angle = math.radians((360 / 60) * minute + (360 / 60) * (second / 60))
second_angle = math.radians((360 / 60) * second)
return hour_angle, minute_angle, second_angle, None, None
# Decimal time calculations
deciday = seconds_since_midnight // 8640
centiday = (seconds_since_midnight % 8640) // 864
seconds_in_centiday = (seconds_since_midnight % 8640) % 864
# Angles for decimal time
deciday_angle = math.radians(360 * (deciday + (seconds_since_midnight % 8640) / 8640) / 10)
centiday_angle = math.radians(360 * (centiday + (seconds_since_midnight % 864) / 864) / 10)
second_angle = math.radians((360 / 864) * seconds_in_centiday)
return deciday_angle, centiday_angle, second_angle, deciday, centiday
[docs]
def prepare_hands_and_angles(
hands: Dict[str, float],
angles: Tuple[float, float, float, Optional[float], Optional[float]],
is_decimal: bool,
) -> List[Tuple[str, float, float]]:
"""Prepare the hands to draw based on the mode (decimal vs.
analog). Returns a list of hands and associated angles to draw.
"""
hands_to_draw = []
angles_to_draw = []
if is_decimal:
# Decimal time: Deciday, Centiday, Second
hands_to_draw = ["deciday", "centiday", "second"]
angles_to_draw = [angles[0], angles[1], angles[2]]
else:
# Analog time: Hour, Minute, Second
hands_to_draw = ["hour", "minute", "second"]
angles_to_draw = [angles[0], angles[1], angles[2]]
# Now we have hands_to_draw and angles_to_draw ready for drawing
hands_and_angles = []
for name, angle in zip(hands_to_draw, angles_to_draw):
# Fetch the corresponding length from the hands dictionary
length = hands[name]
hands_and_angles.append((name, length, angle))
return hands_and_angles
[docs]
def draw_clock_hands(
canvas_config: CanvasConfig, hands_and_angles: List[Tuple[str, float, float]], tag_prefix: str
) -> None:
"""Draw the clock hands based on the calculated hands and angles."""
center = canvas_config.center
canvas_config.canvas.delete(f"{tag_prefix}_hands")
# Draw each clock hand
for name, length, angle in hands_and_angles:
if name == "second":
hand_config = HandConfig(
length, angle, 3, styles["hand_colors"][name], f"{tag_prefix}_hands"
)
draw_hand(canvas_config, hand_config)
else:
base_width = 15 if (name in ("hour", "deciday")) else 10
hand_config = HandConfig(
length, angle, base_width, styles["hand_colors"][name], f"{tag_prefix}_hands"
)
draw_hand(canvas_config, hand_config)
# Draw the center circle for aesthetics
canvas_config.canvas.create_oval(
center[0] - 7,
center[1] - 7,
center[0] + 7,
center[1] + 7,
fill=styles["center_circle_color"],
outline="",
tags=f"{tag_prefix}_hands",
)
[docs]
def update_digital_time(
canvas_config: CanvasConfig,
hands: Dict[str, float],
tag_prefix: str,
is_decimal: bool,
seconds_since_midnight: int,
) -> None:
"""Updates and displays the digital time (either analog or decimal)."""
canvas = canvas_config.canvas
center = canvas_config.center
canvas.delete(f"{tag_prefix}_digital")
if not is_decimal:
# Analog time (24-hour format)
hour = (seconds_since_midnight // 3600) % 24
minute = (seconds_since_midnight // 60) % 60
second = seconds_since_midnight % 60
digital_time = f"{hour:02}:{minute:02}:{second:02}" # 24-hour format
else:
# Decimal time
deciday = seconds_since_midnight // 8640
centiday = (seconds_since_midnight % 8640) // 864
seconds_in_centiday = (seconds_since_midnight % 8640) % 864
digital_time = f"{deciday}.{centiday}.{seconds_in_centiday:03}"
# Display digital time below the clock
digital_time_y = center[1] + hands["second"] + 60 # Adjust vertical position
canvas.create_text(
center[0],
digital_time_y,
text=digital_time,
font=styles["digital_font"],
fill=styles["digital_time_color"],
tags=f"{tag_prefix}_digital",
)
[docs]
def update_clock(
canvas_config: CanvasConfig, hands: Dict[str, float], tag_prefix: str, is_decimal: bool = False
) -> None:
"""Updates the positions of the clock hands and the digital time display.
Uses the styles dictionary for colors and font.
"""
seconds_since_midnight = get_seconds_since_midnight()
# Calculate angles for the clock hands based on time
angles = calculate_angles(seconds_since_midnight, is_decimal)
# Prepare hands and angles for drawing
hands_and_angles = prepare_hands_and_angles(hands, angles, is_decimal)
# Draw clock hands
draw_clock_hands(canvas_config, hands_and_angles, tag_prefix)
# Update digital time
update_digital_time(canvas_config, hands, tag_prefix, is_decimal, seconds_since_midnight)
if not is_decimal:
update_kiloseconds(canvas_config, tag_prefix, int(seconds_since_midnight))
else:
update_decidays(canvas_config, tag_prefix, int(seconds_since_midnight))
canvas_config.canvas.after(
500, update_clock, canvas_config, hands, tag_prefix, is_decimal
) # Update every 500ms
[docs]
def calculate_hand_geometry(
center: Tuple[int, int], length: float, angle: float, base_width: float
) -> Dict[str, Tuple[float, float]]:
"""Calculates the geometry of the clock hand.
Args:
center (tuple): Center of the clock (x, y).
length (int): Length of the hand.
angle (float): Angle of the hand in radians.
base_width (int): Width of the hand base.
Returns:
dict: Coordinates of the hand's key points.
"""
tip = (
center[0] + length * math.sin(angle),
center[1] - length * math.cos(angle),
)
middle = (
center[0] + (length / 2) * math.sin(angle),
center[1] - (length / 2) * math.cos(angle),
)
middle_offset = (
(base_width / 2) * math.cos(angle),
(base_width / 2) * math.sin(angle),
)
base_offset = (
(base_width / 4) * math.cos(angle),
(base_width / 4) * math.sin(angle),
)
return {
"tip": tip,
"middle_right": (middle[0] + middle_offset[0], middle[1] + middle_offset[1]),
"middle_left": (middle[0] - middle_offset[0], middle[1] - middle_offset[1]),
"base_right": (center[0] + base_offset[0], center[1] + base_offset[1]),
"base_left": (center[0] - base_offset[0], center[1] - base_offset[1]),
}
[docs]
def draw_hand(canvas_config: CanvasConfig, hand_config: HandConfig) -> None:
"""Draws a clock hand with an arrow-like shape, where the tip is a single
point, and the hand widens to its base near the center.
Args:
canvas (tk.Canvas): Canvas to draw on.
center (tuple): Center of the clock (x, y).
length (int): Length of the hand.
angle (float): Angle of the hand in radians.
base_width (int): Maximum width of the hand at the middle.
color (str): Color of the hand.
tag (str): Unique tag for the hand.
"""
canvas = canvas_config.canvas
center = canvas_config.center
# Calculate geometry
geometry = calculate_hand_geometry(
center, hand_config.length, hand_config.angle, hand_config.base_width
)
# Draw the hand as a polygon
canvas.create_polygon(
geometry["tip"][0],
geometry["tip"][1],
geometry["middle_right"][0],
geometry["middle_right"][1],
geometry["base_right"][0],
geometry["base_right"][1],
geometry["base_left"][0],
geometry["base_left"][1],
geometry["middle_left"][0],
geometry["middle_left"][1],
fill=hand_config.color,
tags=hand_config.tag,
)
[docs]
def calculate_tick_coordinates(
center: Tuple[int, int], radius: float, angle: float, tick_length: float
) -> Tuple[float, float, float, float]:
"""Calculates the coordinates for the ends of a tick line.
Args:
center (tuple): Center of the circle (x, y).
radius (int): Radius of the circle.
angle (float): Angle of the tick in radians.
tick_length (int): Length of the tick.
Returns:
tuple: Coordinates of the tick line's start and end points.
"""
x1 = center[0] + radius * math.sin(angle)
y1 = center[1] - radius * math.cos(angle)
x2 = center[0] + tick_length * math.sin(angle)
y2 = center[1] - tick_length * math.cos(angle)
return (x1, y1, x2, y2)
[docs]
def calculate_digit_coordinates(
center: Tuple[int, int], tick_length: float, angle: float, offset: int = 5
) -> Tuple[float, float]:
"""Calculates the coordinates for positioning a digit near a tick.
Args:
center (tuple): Center of the circle (x, y).
tick_length (int): Length of the tick.
angle (float): Angle of the tick in radians.
offset (int): Offset from the tick's end for placing the digit.
Returns:
tuple: Coordinates for the digit's placement.
"""
digit_x = center[0] + (tick_length - offset) * math.sin(angle)
digit_y = center[1] - (tick_length - offset) * math.cos(angle)
return (digit_x, digit_y)
[docs]
def draw_inner_scale(
canvas_config: CanvasConfig, radius: float, num_ticks: int, scale_tag: str
) -> None:
"""Draws an inner circular scale with ticks, using the styles dictionary
for tick colors and font.
Args:
canvas_config (CanvasConfig): Canvas and center configuration.
radius (int): Radius of the scale.
num_ticks (int): Number of ticks to draw.
scale_tag (str): Tag for identifying scale elements.
scale_type (str): Type of scale (e.g., "seconds", "centidays").
"""
for i in range(num_ticks):
angle = math.radians(i * (360 / num_ticks))
# Determine tick length
if i % 100 == 0:
tick_length = radius - 15
elif i % 10 == 0:
tick_length = radius - 10
else:
tick_length = radius
# Draw the tick
x1, y1, x2, y2 = calculate_tick_coordinates(
canvas_config.center, radius, angle, tick_length
)
canvas_config.canvas.create_line(
x1, y1, x2, y2, fill=styles["scale_tick_color"], tags=scale_tag
)
# Draw the digit for major ticks
if i % 100 == 0:
digit_x, digit_y = calculate_digit_coordinates(canvas_config.center, tick_length, angle)
canvas_config.canvas.create_text(
digit_x,
digit_y,
text=f"{int(i)}",
font=("Orbitron", 8, "bold"),
fill=styles["scale_digit_color"],
tags=scale_tag,
)
[docs]
def draw_outer_frame(canvas_config: CanvasConfig, radius: float, tag: str) -> None:
"""Draws the metallic outer frame of the clock.
Args:
canvas (tk.Canvas): Canvas to draw on.
center (tuple): Center of the clock (x, y).
radius (int): Radius of the clock.
tag (str): Unique tag for the outer frame.
"""
center = canvas_config.center
canvas_config.canvas.create_oval(
center[0] - radius - 5,
center[1] - radius - 5,
center[0] + radius + 5,
center[1] + radius + 5,
outline=styles["frame_color"],
width=5,
tags=tag,
)
[docs]
def draw_inner_circle(canvas_config: CanvasConfig, radius: float, tag: str) -> None:
"""Draws the inner circle of the clock (background).
Args:
canvas (tk.Canvas): Canvas to draw on.
center (tuple): Center of the clock (x, y).
radius (int): Radius of the clock.
tag (str): Unique tag for the inner circle.
"""
center = canvas_config.center
canvas_config.canvas.create_oval(
center[0] - radius,
center[1] - radius,
center[0] + radius,
center[1] + radius,
fill=styles["inner_color"],
outline="",
tags=tag,
)
[docs]
def draw_tick(
canvas_config: CanvasConfig, radius: float, angle: float, is_major: bool, tag: str
) -> None:
"""Draws a single tick on the clock face.
Args:
canvas (tk.Canvas): Canvas to draw on.
center (tuple): Center of the clock (x, y).
radius (int): Radius of the clock.
angle (float): Angle of the tick in radians.
is_major (bool): Whether the tick is a major (large) tick.
tag (str): Unique tag for the ticks.
"""
center = canvas_config.center
offset = 10 if is_major else 5
x_outer = center[0] + radius * math.sin(angle)
y_outer = center[1] - radius * math.cos(angle)
x_inner = center[0] + (radius - offset) * math.sin(angle)
y_inner = center[1] - (radius - offset) * math.cos(angle)
canvas_config.canvas.create_line(
x_inner,
y_inner,
x_outer,
y_outer,
fill=styles["tick_color"],
width=2 if is_major else 1,
tags=tag,
)
[docs]
def draw_tick_label(
canvas_config: CanvasConfig, radius: float, angle: float, label: str, tag: str
) -> None:
"""Draws a label (number) next to a major tick.
Args:
canvas (tk.Canvas): Canvas to draw on.
center (tuple): Center of the clock (x, y).
radius (int): Radius of the clock.
angle (float): Angle of the tick in radians.
label (str): Label text.
tag (str): Unique tag for the labels.
"""
center = canvas_config.center
x = center[0] + radius * 0.9 * math.sin(angle)
y = center[1] - radius * 0.9 * math.cos(angle)
canvas_config.canvas.create_text(
x,
y,
text=label,
font=("Orbitron", 16, "bold"),
fill=styles["digit_color"],
tags=tag,
)
[docs]
def draw_clock_face(canvas_config: CanvasConfig, radius: float, is_decimal: bool = False) -> None:
"""Draws the clock face with tick marks, labels, and a chrome-style frame.
Args:
canvas_config (CanvasConfig): Canvas and center configuration.
radius (int): Radius of the clock.
is_decimal (bool): Whether this clock uses the decimal time system.
"""
center = canvas_config.center
# Draw outer frame and inner circle
draw_outer_frame(canvas_config, radius, tag=f"{center}_outer_frame")
draw_inner_circle(canvas_config, radius, tag=f"{center}_inner_circle")
# Determine the number of divisions
divisions = 10 if is_decimal else 12
for i in range(divisions):
for j in range(5): # Subdivisions for minor ticks
angle = math.radians((i * 360 / divisions) + (j * (360 / divisions) / 5))
is_major = j == 0
# Draw ticks
draw_tick(canvas_config, radius, angle, is_major, tag=f"{center}_ticks")
# Draw labels for major ticks
if is_major:
label = str(i if is_decimal else (i if i != 0 else 12))
draw_tick_label(canvas_config, radius, angle, label, tag=f"{center}_ticks")
[docs]
def update_clock_with_inner_scale(
canvas_config: CanvasConfig, hands: Dict[str, float], tag_prefix: str, is_decimal: bool = False
) -> None:
"""Updates the clock with an inner scale for tracking seconds within
centiday with neon effects.
Args:
canvas (tk.Canvas): The canvas to draw on.
width (int): The width of the canvas.
height (int): The height of the canvas.
center (tuple): The center of the clock as (x, y).
hands (dict): A dictionary with keys 'hour', 'minute', 'second' or 'deciday', 'centiday',
'second'.
tag_prefix (str): A unique tag prefix to manage hands and digital time for each clock.
is_decimal (bool): Whether this clock uses the decimal time system.
"""
# Update the clock hands and digital time
update_clock(canvas_config, hands, tag_prefix, is_decimal)
# Add inner scale and marker for decimal clock
if is_decimal:
draw_inner_scale(canvas_config, hands["second"] * 0.8, 864, f"{tag_prefix}_inner_scale")
[docs]
def update_kiloseconds(canvas_config: CanvasConfig, scale_tag: str, clock_time: int) -> None:
"""Update and display the kiloseconds at the bottom of the right clock,
below the current time.
Args:
canvas (tk.Canvas): The canvas to draw on.
center (tuple): The center of the clock as (x, y).
radius (int): The radius of the inner scale.
scale_tag (str): A unique tag to manage the scale.
clock_time (int): The number of seconds since midnight.
"""
canvas = canvas_config.canvas
center = canvas_config.center
radius = canvas_config.height * 1.8
# Calculate the kiloseconds (1 Ks = 1000 seconds)
kiloseconds = (
clock_time % 86400
) / 1000 # Kiloseconds since the start of the day (86400 seconds in a day)
# Get the position for displaying the kiloseconds (below the current time)
digit_x = center[0] # Align with the center horizontally
digit_y = center[1] + 0.25 * radius # Position it below the current time
# Clear old kiloseconds text (optional, but useful for updates)
canvas.delete(f"{scale_tag}_ks")
# Display the kiloseconds number (formatted to 3 decimal places)
canvas.create_text(
digit_x,
digit_y,
text=f"{kiloseconds:.3f} Ks",
font=styles["font"],
fill=styles["kilosecond_color"],
tags=f"{scale_tag}_ks",
)
[docs]
def update_decidays(canvas_config: CanvasConfig, scale_tag: str, clock_time: int) -> None:
"""Update the display of decidays on a canvas.
This function calculates the decidays (1 deciday = 8640 seconds) based on the current
`clock_time`, and updates the specified canvas with the calculated value. The deciday
value is displayed below the kiloseconds on the canvas.
Args:
canvas_config: A configuration object containing the canvas, center, and height
information for rendering.
- canvas: The drawing canvas where the decidays text will be displayed.
- center: A tuple of (x, y) coordinates representing the center of the canvas.
- height: The base height used for scaling the display radius.
scale_tag (str): A unique tag used to identify and update the decidays text
element on the canvas.
clock_time (int): The current time in seconds since midnight.
Returns:
None
Notes:
- The decidays are calculated as:
`decidays = (clock_time % 86400) / 8640`
where 86400 seconds represents a full day.
- The text is formatted to 5 decimal places for precision.
Example:
Assuming `canvas_config` has a canvas centered at (100, 100) and a height of 50:
>>> update_decidays(canvas_config, "time_display", 43200)
# Displays "5.00000 dd" on the canvas centered at (100, 100 + 0.25 * radius).
"""
# Calculate the decidays (1 deciday = 8640 seconds)
canvas = canvas_config.canvas
center = canvas_config.center
radius = canvas_config.height * 1.8
decidays = (
clock_time % 86400
) / 8640 # Decidays since the start of the day (86400 seconds in a day)
# Get the position for displaying the decidays (below the kiloseconds)
digit_x = center[0] # Align with the center horizontally
digit_y = center[1] + 0.25 * radius
# Clear old decidays text (optional, but useful for updates)
canvas.delete(f"{scale_tag}_dd")
# Display the decidays number (formatted to 3 decimal places)
canvas.create_text(
digit_x,
digit_y,
text=f"{decidays:.5f} dd",
font=styles["font"],
fill=styles["deciday_color"],
tags=f"{scale_tag}_dd",
)
[docs]
def run_clock() -> None:
"""Main function to set up the clock window and start the clocks."""
# Window dimensions
width, height = 800, 500 # Increased height to accommodate digital time
clock_radius = 150 # Radius for each clock
clock1_center = (200, height // 2 - 50) # Center of first clock
clock2_center = (600, height // 2 - 50) # Center of second clock
# Hand configurations
hands = {
"hour": clock_radius * 0.5,
"minute": clock_radius * 0.8,
"second": clock_radius * 0.9,
"deciday": clock_radius * 0.5,
"centiday": clock_radius * 0.8,
}
# Tkinter setup
root = tk.Tk()
root.title("Analog Clocks")
canvas = tk.Canvas(root, width=width, height=height, bg=styles["background_color"])
canvas.pack()
# Draw clock faces and update each clock
for center, tag_prefix, is_decimal in zip(
[clock1_center, clock2_center], ["duodecimal", "decimal"], [False, True]
):
canvas_config = CanvasConfig(canvas, width, height, center)
# Draw clock face (outer circle)
canvas.create_oval(
center[0] - clock_radius,
center[1] - clock_radius,
center[0] + clock_radius,
center[1] + clock_radius,
outline=styles["outline_color"],
width=3, # Wider outline for emphasis
)
draw_clock_face(canvas_config, clock_radius, is_decimal)
# draw_circuit_lines(canvas, center, clock_radius)
# Update the clocks
if is_decimal:
# Update the decimal clock with inner scale and seconds marker
update_clock_with_inner_scale(canvas_config, hands, tag_prefix, is_decimal)
else:
# Update the standard clock
update_clock(canvas_config, hands, tag_prefix, is_decimal)
root.mainloop()