I made a countdown timer using Tkinter in python, but it's very and the seconds aren't real seconds (the timer is faster than it should be).
The after()
function of tkinter doesn't wait exactly the specified amount of time, so I can't just substract 1 millisecond every time it waits 1 millisecond using after(1)
, it wouldn't be accurate. So now the program finds the exact amount of time that has passed while waiting 1ms with after(1)
and then substract this amount from the timer.
Could anyone suggest an edit or just edit my program to solve these problems?
Here's the program:
from tkinter import *
import time
import datetime
class root(Tk):
def __init__(self):
super(root, self).__init__()
self.title("Timer")
self.buttonplay = Button(self, text = "Play", fg= 'green', command = self.play)
self.buttonplay.pack()
self.buttonpause = Button(self, text = "Pause", fg = "red", command=self.pause)
self.buttonpause.pack()
self.buttonreset = Button(self, text = "Reset", fg = "red", command=self.reset)
self.buttonreset.pack()
self.createTimers()
def play(self):
self.timeit=True
self.timer1.configure(bg='#1C953D')
self.doTimer()
def pause(self):
self.timeit=False
self.timer1.configure(bg='#454545')
def reset(self):
self.timer1.destroy()
self.createTimers()
def createTimers(self):
self.total_minute = 1
self.total_second = 5
self.total_micros = 0
self.total = self.total_second self.total_minute *60 self.total_micros*0.000001
self.originalTime = datetime.datetime.now()
self.micros = self.originalTime.microsecond
self.seconds = self.originalTime.second
self.minutes = self.originalTime.minute
self.time1 = StringVar()
self.time1.set(str(self.total_minute).rjust(2, '0') ':' str(self.total_second).rjust(2, '0') '.' str(self.total_micros)[0:3].rjust(3, '0'))
self.timer1 = Label(self, textvariable=self.time1, bg='#454545', fg='white', font ="Gadugi 40 bold")
self.timer1.pack()
self.timer1.configure(bg='#454545')
def doTimer(self):
if (self.total_second self.total_minute *60 self.total_micros*0.000001) >0: #Checks if the timer ended
if self.timeit:
self.nowTime = datetime.datetime.now()
self.toDim = self.nowTime.microsecond
while self.toDim > 0:
if self.micros > 0:
self.micros = self.micros -1
self.toDim = self.toDim -1
else:
if self.seconds > 0:
self.seconds = self.seconds -1
self.micros = 999999
else:
self.minutes = self.minutes -1
self.seconds = 59
self.DimTime = datetime.datetime(self.originalTime.year, self.originalTime.month, self.originalTime.day, self.originalTime.hour, self.minutes, self.seconds, self.micros)
self.waitMicros = self.originalTime - self.DimTime
self.total_micros = self.total_micros - self.waitMicros.microseconds
if self.total_micros <0:
self.total_second = self.total_second -1
self.total_micros = 999999
if self.total_second <0:
self.total_minute = self.total_minute -1
self.total_second = 59
self.time1.set(str(self.total_minute).rjust(2, '0') ':' str(self.total_second).rjust(2, '0') '.' str(self.total_micros)[0:3].rjust(3, '0'))
self.after(1, self.doTimer)
else:
self.time1.set('00:00.000')
self.timer1.configure(bg='#FF0000')
self.after(3000, self.reset)
root = root()
root.mainloop()
Here's a video showing the problem.
CodePudding user response:
def play(self):
self.timeit = True
self.timer1.configure(bg='#1C953D')
self.start_time = time.time()
self.total_start = self.seconds self.minutes * 60 self.micros * 0.000001
self.doTimer()
def pause(self):
self.timeit = False
self.timer1.configure(bg='#454545')
def reset(self):
self.timer1.destroy()
self.createTimers()
def createTimers(self):
self.start_time = time.time()
self.minutes = 1
self.seconds = 5
self.micros = 0
self.total_start = self.seconds self.minutes * 60 self.micros * 0.000001
self.time1 = StringVar()
self.time1.set(str(self.minutes).rjust(2, '0') ':' str(self.seconds).rjust(2, '0') '.' str(
self.micros)[0:3].rjust(3, '0'))
self.timer1 = Label(self, textvariable=self.time1, bg='#454545', fg='white', font="Gadugi 40 bold")
self.timer1.pack()
self.timer1.configure(bg='#454545')
def doTimer(self):
if (self.seconds self.minutes * 60 self.micros * 0.000001) > 0: # Checks if the timer ended
if self.timeit:
self.time_left = self.start_time - time.time() self.total_start
self.minutes = int(self.time_left) // 60
self.seconds = int(self.time_left) % 60
self.micros = int((self.time_left - int(self.time_left)) * 1000000)
self.time1.set(
str(self.minutes).rjust(2, '0') ':' str(self.seconds).rjust(2, '0') '.' str(
self.micros)[0:3].rjust(3, '0'))
self.after(1, self.doTimer)
else:
self.time1.set('00:00.000')
self.timer1.configure(bg='#FF0000')
self.after(3000, self.reset)