I have a countdown program (code below) that should start counting down from whatever length of time you have put in (you all know how a timer works, right?). But the tkinter window simply freezes when you press start but does not return any error until a windows error message saying that the window is not responding pops up. I have included some print statements as I was trying to debug it and it shows in shell that the program is working as it repeatedly prints c .Does anyone know how to sort out this problem?
import tkinter as tk
import time
def change(direction, stringvar, up_button, down_button):
if direction == 'up':
stringvar.set(stringvar.get()+1)
down_button.config(state = 'normal')
if int(stringvar.get())== 59:
up_button.config(state = 'disabled')
if direction == 'down':
stringvar.set(stringvar.get()-1)
up_button.config(state = 'normal')
if stringvar.get()== 0:
down_button.config(state = 'disabled')
def startTimer():
hourEntry.destroy()
minuteEntry.destroy()
secondEntry.destroy()
print('a')
hourLab = tk.Label(root, textvariable = hourText)
minuteLab = tk.Label(root, textvariable = minuteText)
secondLab = tk.Label(root, textvariable = secondText)
print('b')
hourLab.grid(row = 1, column = 0)
minuteLab.grid(row = 1, column = 1)
secondLab.grid(row = 1, column = 2)
while hourText.get() != 0 or minuteText != 0 or secondText !=0:
print('c')
time.sleep(1)
secondText.set(secondText.get()-1)
if int(secondText.get()) == 0:
secondText.set(59)
if int(minuteText.get()) == 0:
if int(hourText.get()) == 0:
continue
else:
hourText.set(str(int(hourText.get())-1))
else:
minuteText.set(str(int(minuteText.get())-1))
root = tk.Tk()
root.title('Timer')
hourText = tk.IntVar()
minuteText = tk.IntVar()
secondText = tk.IntVar()
hourText.set(1)
minuteText.set(1)
secondText.set(1)
## create buttons and entry boxes using loop
up1 = tk.Button(root, text = '^^^', command = lambda: change('up', hourText, up1, down1))
up2 = tk.Button(root, text = '^^^', command = lambda: change('up', minuteText, up2, down2))
up3 = tk.Button(root, text = '^^^', command = lambda: change('up', secondText, up3, down3))
hourEntry = tk.Entry(root, textvariable = hourText, width = 5)
minuteEntry = tk.Entry(root, textvariable = minuteText, width = 5)
secondEntry = tk.Entry(root, textvariable = secondText, width = 5)
down1 = tk.Button(root, text = '...', command = lambda: change('down', hourText, up1, down1))
down2 = tk.Button(root, text = '...', command = lambda: change('down', minuteText, up2, down2))
down3 = tk.Button(root, text = '...', command = lambda: change('down', secondText, up3, down3))
start = tk.Button(root, text = 'Start', command = startTimer)
up1.grid(row = 0, column = 0, pady = 5, padx = 5)
up2.grid(row = 0, column = 1)
up3.grid(row = 0, column = 2, padx = 5)
hourEntry.grid(row = 1, column = 0, padx = 2, pady = 5)
minuteEntry.grid(row = 1, column = 1, padx = 2, pady = 5)
secondEntry.grid(row = 1, column = 2, padx = 2, pady = 5)
down1.grid(row = 2, column = 0)
down2.grid(row = 2, column = 1)
down3.grid(row = 2, column = 2)
start.grid(row = 3, columnspan = 3, pady = 5)
root.mainloop()
To implement your program :
import tkinter as tk
import time
def change(direction, stringvar, up_button, down_button):
if direction == 'up':
stringvar.set(stringvar.get()+1)
down_button.config(state = 'normal')
if int(stringvar.get())== 59:
up_button.config(state = 'disabled')
if direction == 'down':
stringvar.set(stringvar.get()-1)
up_button.config(state = 'normal')
if stringvar.get()== 0:
down_button.config(state = 'disabled')
def timer():
if hourText.get() != 0 or minuteText != 0 or secondText !=0:
print('c')
time.sleep(1)
secondText.set(secondText.get()-1)
if int(secondText.get()) == 0:
secondText.set(59)
if int(minuteText.get()) == 0:
if int(hourText.get()) == 0:
pass
else:
hourText.set(str(int(hourText.get())-1))
else:
minuteText.set(str(int(minuteText.get())-1))
root.after(1, timer)
def startTimer():
hourEntry.destroy()
minuteEntry.destroy()
secondEntry.destroy()
print('a')
hourLab = tk.Label(root, textvariable = hourText)
minuteLab = tk.Label(root, textvariable = minuteText)
secondLab = tk.Label(root, textvariable = secondText)
print('b')
hourLab.grid(row = 1, column = 0)
minuteLab.grid(row = 1, column = 1)
secondLab.grid(row = 1, column = 2)
root.after(1, timer)
root = tk.Tk()
root.title('Timer')
hourText = tk.IntVar()
minuteText = tk.IntVar()
secondText = tk.IntVar()
hourText.set(1)
minuteText.set(1)
secondText.set(1)
## create buttons and entry boxes using loop
up1 = tk.Button(root, text = '^^^', command = lambda: change('up', hourText, up1, down1))
up2 = tk.Button(root, text = '^^^', command = lambda: change('up', minuteText, up2, down2))
up3 = tk.Button(root, text = '^^^', command = lambda: change('up', secondText, up3, down3))
hourEntry = tk.Entry(root, textvariable = hourText, width = 5)
minuteEntry = tk.Entry(root, textvariable = minuteText, width = 5)
secondEntry = tk.Entry(root, textvariable = secondText, width = 5)
down1 = tk.Button(root, text = '...', command = lambda: change('down', hourText, up1, down1))
down2 = tk.Button(root, text = '...', command = lambda: change('down', minuteText, up2, down2))
down3 = tk.Button(root, text = '...', command = lambda: change('down', secondText, up3, down3))
start = tk.Button(root, text = 'Start', command = startTimer)
up1.grid(row = 0, column = 0, pady = 5, padx = 5)
up2.grid(row = 0, column = 1)
up3.grid(row = 0, column = 2, padx = 5)
hourEntry.grid(row = 1, column = 0, padx = 2, pady = 5)
minuteEntry.grid(row = 1, column = 1, padx = 2, pady = 5)
secondEntry.grid(row = 1, column = 2, padx = 2, pady = 5)
down1.grid(row = 2, column = 0)
down2.grid(row = 2, column = 1)
down3.grid(row = 2, column = 2)
start.grid(row = 3, columnspan = 3, pady = 5)
root.mainloop()
Tkinter uses a method (Tk.after) that allow the user to overcome the tk mainloop. (The window does not wait for the function to finish).
It allows us to update manually all the widgets (canvas, button, label [ect...])
This is a method I always use in my tkinter applications, because I don't trust tk.mainloop () to do what I want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With