ttk StringVar doesnt change

49 views Asked by At

when i click the start button, the only thing that happpens is the button becoming disabled. nothing else happens. any idea why the timer doesnt start?

The idea as you see is to get the entry and split it by ":" to get the hour,minute, and second when i hit the start button. the timer algorithm runs and the label below the button changes accordingly.

from ctypes import windll

windll.shcore.SetProcessDpiAwareness(1)

import tkinter as tk
from tkinter import ttk

def start():
    button.config(state="disabled")
    entry.config(state="disabled")
    update_timer()

def update_timer():
    global hour, minute, second
    timer.set(f'{hour:02}:{minute:02}:{second:02}')
    print(timer)
    if second == 0:
        if minute == 0:
            if hour == 0:
                button.config(state="enabled")
                entry.config(state="enabled")
                return
            else:
                hour -= 1
                minute = 59
                second = 59
        else:
            minute -= 1
            second = 59
    else:
        second -= 1
    window.after(1000, update_timer)

window = tk.Tk()

window.geometry("300x150")
window.resizable(False,False)

entry = ttk.Entry(window)
entry.pack()

button = ttk.Button(window, text="start", command=start)
button.pack()

hour = minute = second = 0

timer = tk.StringVar(value="00:00:00")
label = ttk.Label(window, textvariable=timer, font="comicsans 30 bold")
label.pack(pady=10)

window.mainloop()

i tried using the regular varaibles and add them directly into the label but that didnt work

2

There are 2 answers

0
Bryan Oakley On BEST ANSWER

The problem is that you've initialized hour, minute, and second to zero, and then the first thing you do is check if those are zero and return from the function.

If you initialize those values to something else, your code will work. For example, change start to look like this for a 30 second timer:

def start():
    global second
    second = 30
    button.config(state="disabled")
    entry.config(state="disabled")
    update_timer()
0
acw1668 On

Note that update_timer() will be executed only once when hour, minute and second are all zero:

def update_timer():
    global hour, minute, second
    timer.set(f'{hour:02}:{minute:02}:{second:02}')
    print(timer)
    if second == 0:
        if minute == 0:
            if hour == 0:
                # this block will be executed if hour = minute = second = 0
                button.config(state="enabled")
                entry.config(state="enabled")
                return
            else:
                hour -= 1
                minute = 59
                second = 59
        else:
            minute -= 1
            second = 59
    else:
        second -= 1
    # below line will not be executed if hour = minute = second = 0
    window.after(1000, update_timer)

Actually you don't need to declare hour, minute and second as global variables, just pass them as arguments to update_timer() as below:

def start():
    try:
        # assume that input string looks like "h:m:s"
        # then we can extract hour, minute and second from the input string
        hour, minute, second = [int(x) for x in entry.get().strip().split(":")]
        button.config(state="disabled")
        entry.config(state="disabled")
        update_timer(hour, minute, second)
    except Exception as ex:
        print(ex)

def update_timer(hour, minute, second):
    timer.set(f'{hour:02}:{minute:02}:{second:02}')
    print(timer.get())
    if second == 0:
        if minute == 0:
            if hour == 0:
                button.config(state="enabled")
                entry.config(state="enabled")
                return
            else:
                hour -= 1
                minute = 59
                second = 59
        else:
            minute -= 1
            second = 59
    else:
        second -= 1
    window.after(1000, update_timer, hour, minute, second)