Search code examples
pythondatetimetkintertimer

Why does my check for the timer completion return True earlier, and repeatedly? Tkinter


For some reason, in checkTimer(), if datetime.now() == target_time: triggers before the target time, and repeatedly triggers afterward. I have tried to fix this for several hours to no avail. Why is this?

Code:

# IMPORTS #

import tkinter as tk
from tkinter.font import *
from playsound import playsound
import os
from itertools import cycle
import json
from tkinter import PhotoImage
import time
from datetime import datetime, timedelta
from ctypes import Structure, windll, c_uint, sizeof, byref

class LASTINPUTINFO(Structure):
    _fields_ = [
        ('cbSize', c_uint),
        ('dwTime', c_uint),
    ]

def get_idle_duration():
    lastInputInfo = LASTINPUTINFO()
    lastInputInfo.cbSize = sizeof(lastInputInfo)
    windll.user32.GetLastInputInfo(byref(lastInputInfo))
    millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
    return millis / 1000.0

t = time.localtime()
current_hrs = time.strftime("%H")
current_minutes = time.strftime("%M")
current_secs = time.strftime("%S")
current_hrs = int(current_hrs)
current_minutes = int(current_minutes)
current_secs = int(current_secs)
print(current_secs)
print(current_minutes)
print(current_hrs)


imagesCreated = 0
inARow = 0

# VARIABLES #

# minutes = cycle((25, 5, 25, 5, 25, 5, 25, 5, 25, 30))
minutes = cycle((1, 1))
notificationText = ""
directory = os.getcwd()
isTimerDone = False
onBreak = False
pomodoros = 0

jsonFile = open("Real-Time Drowsiness Detection OpenCV Python Source Code/VALUE.json", 'r+')
data = json.load(jsonFile)
drowsy = 0
workTime = 25

# FUNCTIONS #


# TKINTER #

window = tk.Tk()

window.title("Focus-Ware")
bigFontRegular = Font(
    family="Helvetica",
    size=35,
)
titleFont = Font(
    family="Helvetica",
    size=50
)
buttonimage = PhotoImage(file="Images/start.png")
bigFontItalic = Font(
    family="Helvetica",
    size=35,
    slant="italic"
)
regularFontItalic = Font(
    family="Helvetica",
    size=25,
    slant="italic"
)
window.geometry("510x600")
title = tk.Label(
    text="Focus-Ware",
    font=titleFont,
    foreground="black",
)
timerTitle = tk.Label(
    text="Timer:",
    font=bigFontItalic,
    foreground="black"
)
timer = tk.Label(
    text="Not Started",
    font=bigFontRegular,
    foreground="black"
)

reminderTitle = tk.Label(
    text=notificationText,
    font=regularFontItalic,
    foreground="black"
)

reminder = tk.Label(
    text="Last Notification:",
    font=bigFontItalic,
    foreground="black"
)


def doNothing():
    return "nothing"


pomodoroDone = False
target_hours = current_hrs
target_minutes = current_minutes
target_secs = current_secs
periods = 0

def setTimer():
    global target_minutes
    global target_hours
    global current_hrs
    global current_minutes
    global onBreak
    global periods
    global current_secs
    global target_time
    target_time = datetime.now() + timedelta(minutes=1)
    t = time.localtime()
    current_hrs = time.strftime("%H")
    current_minutes = time.strftime("%M")
    current_hrs = int(current_hrs)
    current_minutes = int(current_minutes)
    current_secs = int(current_secs)
    timer.config(text="In Progress")
    window.after(10000, checkTimer)

target_time = datetime.now()

def checkTimer():
    global jsonFile
    global target_minutes
    global target_hours
    global current_hrs
    global current_minutes
    global onBreak
    global periods
    global drowsy
    global current_secs
    global target_secs
    global target_time
    target_time = datetime.now()
    if get_idle_duration() >= 600:
        reminderTitle.config(text="Make sure to work!")
        playsound(f'{os.getcwd()}/Audio/GETTOWORK.wav')
    if drowsy == 1:
        playsound(f'{os.getcwd()}/Audio/wakeup.wav')
    if datetime.now() == target_time:
        onBreak = not onBreak
        timer.config(text="Completed")
        playsound(f'{os.getcwd()}/Audio/notification.mp3')
        if onBreak:
            if periods == 4:
                target_time = datetime.now() + timedelta(minutes=30)
                if target_minutes >= 60:
                    target_minutes -= 60
                    target_hours += 1
                periods = 0
            else:
                target_time = datetime.now() + timedelta(minutes=5)
                if target_minutes >= 60:
                    target_minutes -= 60
                    target_hours += 1

        else:
            target_time = datetime.now() + timedelta(minutes=1)
            if target_minutes >= 60:
                target_minutes -= 60
                target_hours += 1
            periods += 1
    else:
        timer.config(text="In Progress")
    window.after(500, checkTimer)




#
#
# def timerDone():
#     global onBreak
#     global isTimerDone
#     global workTime
#     global drowsy
#     drowsy = int(data["VALUE"])
#     if drowsy == 1:
#         workTime = 20
#     else:
#         workTime = 25
#     isTimerDone = True
#     reminderTitle.config(text="The timer is done!")
#     onBreak = not (onBreak)
#     if onBreak:
#         reminderTitle.config(text="Go on break!")
#     else:
#         reminderTitle.config(text="Get to work!")
#     window.after(2000, bruhwhatbruh)
#     if onBreak:
#         timer.config(text=f'Completed, take a break!')
#     else:
#         timer.config(text=f'Completed, get to work!')
#     playsound(f'{os.getcwd()}/Audio/notification.mp3')
#
#
# def bruhwhatbruh():
#     drowsy = int(data["VALUE"])
#     if drowsy == 1:
#         reminderTitle.config(text="You look tired!")
#
#
# def betweenTimers():
#     global inARow
#     global workTime
#     drowsy = int(data["VALUE"])
#     if drowsy == 1:
#         reminderTitle("You look tired!")
#         playsound(f'{os.getcwd()}/Audio/notification.mp3')
#         inARow += 1
#         workTime = 20
#     else:
#         workTime = 25
#     if inARow == 3:
#         inARow = 0
#         reminderTitle("Please take a break!")
#         playsound(f'{os.getcwd()}/Audio/notification.mp3')
#
#
# def setSubTimers(wkt):
#     for i in range(2):
#         if i == 0 or i == 1:
#             pass
#         else:
#             window.after((workTime * wkt) + round(2 / i) * 60 * 1000, betweenTimers)
#
#
# def setTimer(mins=25):
#     timer.config(text="In Progress")
#     setSubTimers(0)
#     window.after(2 * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     window.after(workTime + 5 * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     setSubTimers(1)
#     window.after(workTime + 5 + workTime * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     window.after(workTime + 5 + workTime + 5 * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     setSubTimers(2)
#     window.after(workTime + 5 + workTime + 5 + workTime * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     window.after(workTime + 5 + workTime + 5 + workTime + 5 * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     setSubTimers(3)
#     window.after(workTime + 5 + workTime + 5 + workTime + 5 + workTime * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     window.after(workTime + 5 + workTime + 5 + workTime + 5 + workTime + 5 * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     setSubTimers(4)
#     window.after(workTime + 5 + workTime + 5 + workTime + 5 + workTime + 5 + workTime * 60 * 1000, timerDone)
#     timer.config(text="In Progress")
#     window.after(workTime + 5 + workTime + 5 + workTime + 5 + workTime + 5 + workTime + 30 * 60 * 1000, timerDone)
#

def resetTimer():
    timer.config(text="Not Started")


def reminder_f():
    reminderTitle.config(text="Remember to pay attention!")
    playsound(f'{os.getcwd()}/Audio/notification.mp3')


Start = tk.Button(
    command=setTimer,
    text="Start Pomodoro",
    image=buttonimage
)
Start.config(height=100, width=100)
# DRIVER CODE #

# LOOP #
title.pack()
reminder.pack(pady=40)
reminderTitle.pack()
Start.pack()
timerTitle.pack(pady=40)
timer.pack()

window.mainloop()

Solution

  • You have reset target_time by the line target_time = datetime.now() inside checkTimer(), so datetime.now() == target_time will be evaluated as True.

    Remove that line. Also better use datetime.now() >= target_time instead:

    def checkTimer():
        ...
        #target_time = datetime.now()   # remove this line
        ...
        if datetime.now() >= target_time:  # used >= instead of ==
            ...
        ...