Angelo Catana
Angelo Catana

Reputation: 37

Seven segment digits clock with the system time in python Tkinter with strftime

I need a seven-segment clock with time.strftime. I have this for the clock:

import sys
from tkinter import *
import time

def tick():
    time_string = time.strftime("%M:%S")
    clock.config(text=time_string)
    clock.after(200, tick)

root = Tk()
clock = Label(root, font = ("times", 250, "bold"), bg="white")
clock.grid(row=0, column=1)
tick()
root.mainloop()

And this for the digits:

offsets = (
    (0, 0, 1, 0),  # top
    (1, 0, 1, 1),  # upper right
    (1, 1, 1, 2),  # lower right
    (0, 2, 1, 2),  # bottom
    (0, 1, 0, 2),  # lower left
    (0, 0, 0, 1),  # upper left
    (0, 1, 1, 1),  # middle
)

digits = (
    (1, 1, 1, 1, 1, 1, 0),  # 0
    (0, 1, 1, 0, 0, 0, 0),  # 1
    (1, 1, 0, 1, 1, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1),  # 3
    (0, 1, 1, 0, 0, 1, 1),  # 4
    (1, 0, 1, 1, 0, 1, 1),  # 5
    (1, 0, 1, 1, 1, 1, 1),  # 6
    (1, 1, 1, 0, 0, 0, 0),  # 7
    (1, 1, 1, 1, 1, 1, 1),  # 8
    (1, 1, 1, 1, 0, 1, 1),  # 9
    (1, 1, 1, 0, 1, 1, 1),  # 10=A
    (0, 0, 1, 1, 1, 1, 1),  # 11=b
    (1, 0, 0, 1, 1, 1, 0),  # 12=C
    (0, 1, 1, 1, 1, 0, 1),  # 13=d
    (1, 0, 0, 1, 1, 1, 1),  # 14=E
    (1, 0, 0, 0, 1, 1, 1),  # 15=F
)


class Digit:
    def __init__(self, canvas, *, x=10, y=10, length=20, width=3):
        self.canvas = canvas
        l = length
        self.segs = []
        for x0, y0, x1, y1 in offsets:
            self.segs.append(canvas.create_line(
                x + x0*l, y + y0*l, x + x1*l, y + y1*l,
                width=width, state = 'hidden'))
    def show(self, num):
        for iid, on in zip(self.segs, digits[num]):
            self.canvas.itemconfigure(iid, state = 'normal' if on else 'hidden')

But, I have no idea how to combine them.

Any improvements of the actual code will be appreciated, and if you find that something should be removed or replaced, feel free to do the change. I don't need to use this exact implementation, but this is all I have. If there is a function in a library or something to make the job a hole lot easier, please let me know.

Upvotes: 1

Views: 1738

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15236

Ok so here is my attempt to convert strftime to a 7 segment clock based on the code you provided.

My goal was to generate a list of canvas's for each digit of the formatted timestrafe string. Then on each lap of the clock simply use the Digit class to update each canvas item.

Let me know if you have any questions.

import tkinter as tk
import time
# Order 7 segments clockwise from top left, with crossbar last.
# Coordinates of each segment are (x0, y0, x1, y1) 
# given as offsets from top left measured in segment lengths.
offsets = (
    (0, 0, 1, 0),  # top
    (1, 0, 1, 1),  # upper right
    (1, 1, 1, 2),  # lower right
    (0, 2, 1, 2),  # bottom
    (0, 1, 0, 2),  # lower left
    (0, 0, 0, 1),  # upper left
    (0, 1, 1, 1),  # middle
    )
# Segments used for each digit; 0, 1 = off, on.
digits = (
    (1, 1, 1, 1, 1, 1, 0),  # 0
    (0, 1, 1, 0, 0, 0, 0),  # 1
    (1, 1, 0, 1, 1, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1),  # 3
    (0, 1, 1, 0, 0, 1, 1),  # 4
    (1, 0, 1, 1, 0, 1, 1),  # 5
    (1, 0, 1, 1, 1, 1, 1),  # 6
    (1, 1, 1, 0, 0, 0, 0),  # 7
    (1, 1, 1, 1, 1, 1, 1),  # 8
    (1, 1, 1, 1, 0, 1, 1),  # 9
    (1, 1, 1, 0, 1, 1, 1),  # 10=A
    (0, 0, 1, 1, 1, 1, 1),  # 11=b
    (1, 0, 0, 1, 1, 1, 0),  # 12=C
    (0, 1, 1, 1, 1, 0, 1),  # 13=d
    (1, 0, 0, 1, 1, 1, 1),  # 14=E
    (1, 0, 0, 0, 1, 1, 1),  # 15=F
)

class Digit:
    def __init__(self, canvas, *, x=10, y=10, l=20, wt=3):
        self.canvas = canvas
        canvas.delete("all")
        self.segs = []
        for x0, y0, x1, y1 in offsets:
            self.segs.append(canvas.create_line(x + x0*l, y + y0*l, x + x1*l, y + y1*l, width=wt, state='hidden'))

    def show(self, num):
        for iid, on in zip(self.segs, digits[num]):
            self.canvas.itemconfigure(iid, state='normal' if on else 'hidden')

def tick():
    global canvas_list
    for ndex, num in enumerate(time.strftime("%M:%S").replace(':', '')):
        Digit(canvas_list[ndex]).show(int(num))
    root.after(1000, tick)

root = tk.Tk()
clock_frame = tk.Frame(root)
clock_frame.grid(row=1, column=0)

canvas_list = []

time_col = 0
canvas_count = 0

for i in range(5):
    if i == 2:
        tk.Label(clock_frame, text=":", font = ("times", 40, "bold")).grid(row=0, column=time_col)
        time_col += 1
    else:
        canvas_list.append(tk.Canvas(clock_frame, width=30, height=50))
        canvas_list[canvas_count].grid(row=0, column=time_col)
        canvas_count += 1
        time_col += 1

tick()
root.mainloop()

Keep in mind the OP's code was just looking at min/sec so this clock will reflect that.

Results:

enter image description here

Upvotes: 1

Related Questions