How can a function run repeatedly in background without affecting the functions of the GUI?

Question:

I am working on a school project where I made a GUI Reminder application using customTkinter module and mysql database with two tables named user and reminder.

user Table will contain data like this
user Table Structure

reminder table will contain data like this
reminder table structure

THE CODE IS Updated

The code is given below:

import time
from datetime import datetime,date
import mysql.connector as mysql
import customtkinter as ctk
import schedule
from tkinter import ttk
from tkcalendar import Calendar,DateEntry
from tktimepicker import SpinTimePickerModern,constants
from plyer import notification
ctk.set_appearance_mode("system")
ctk.set_default_color_theme("blue")
mydb=mysql.connect(host="localhost",user ="root",passwd ="XXX",buffered=True)
cursor = mydb.cursor()
def create_database():
    cursor.execute("create database if not exists Remind_it")
    cursor.execute("use Remind_it")
    '''cursor.execute("create table user (U_no int(3) primary key,Name varchar(20),Password varchar(20) not null )")
    cursor.execute("create table reminder (U_no int(3),Rtitle varchar(30),Rdate date ,Rtime time,Rpriority varchar(10),status varchar(10),foreign key(U_no) references user(U_no))")
    print("done")'''

create_database()
window = ctk.CTk()
window.geometry("700x400")
#window.config(bg="#a8d9dd")
window.resizable(width=False,height=False)
window.title('Remind it')
#window.iconphoto(False, tkinter.PhotoImage(file=r"C:UsersAcerOneDriveDocumentspythone code______script____gamemultiplication gameBig Shoes - Torso.png"))

label_title = ctk.CTkLabel(master=window, text="Remind IT", font=("Arial",85),)

def screen1():
    label_title.place(x=165, y=145)
    login_button.place(x=165,y=245)

head_lable = ctk.CTkLabel(master=window, text="Remind IT", font=("Arial",45),)
login_label = ctk.CTkLabel(master=window, text="Login", font=("Arial",42),)
uid_label=ctk.CTkLabel(master=window, text="UserId :-", font=("Arial",35),)
pass_label=ctk.CTkLabel(master=window, text="Password :-", font=("Arial",35),)
user_name = ctk.StringVar()
password=ctk.StringVar()
user_input = ctk.CTkEntry(window,font=("Arial",22),textvariable=user_name)
pass_input = ctk.CTkEntry(window,show="*",font=("Arial",22),textvariable=password)
def login():
    user = user_input.get()
    passwd= pass_input.get()
    cursor.execute("SELECT * FROM user WHERE name=%s AND password=%s", (user,passwd))
    result = cursor.fetchone()
    if result:
        screen3()
        

def screen3 ():
    login_label.place_forget()
    uid_label.place_forget()
    pass_label.place_forget()
    user_input.place_forget()
    pass_input.place_forget()
    lng_button.place_forget()
    create_btn.place(x=235,y=186)
    view_btn.place(x=235,y=286)
    exit_btn.place(x=135,y=200)
    updates_btn.place(x=235,y=386)
title_lable=ctk.CTkLabel(master=window, text="Reminder title :-", font=("Arial",25),)
date_lable=ctk.CTkLabel(master=window, text="date(dd-mm-yyyy) :-", font=("Arial",25),)
time_lable=ctk.CTkLabel(master=window, text="time (HH:MM:SS):-", font=("Arial",25),)
priority_lable=ctk.CTkLabel(master=window, text="priority :-", font=("Arial",25),)
cal=DateEntry(window,mindate=date.today(),width=16,background="magenta3",date_pattern="yyyy-mm-dd")
#t =SpinTimePickerModern(window)
#t.addAll(constants.HOURS24)
#theme=AnalogThemes(t)
title=ctk.StringVar()
date=ctk.StringVar()
timevar=ctk.StringVar()
priority_var=ctk.StringVar()
title_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=title)
#date_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=date)
time_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=timevar)
priority=ctk.CTkSegmentedButton(window,values=["High", "Medium", "Low"],variable=priority_var)

def create_reminder():
    print("aa")
    title=title_input.get()
    date=cal.get_date()
    time=time_input.get()
    pr=priority.get()
    uno=0
    
    cursor.execute("SELECT U_no FROM user WHERE name = %s AND password = %s", (user_input.get(),pass_input.get()))
    result = cursor.fetchone()
    if result:
        for i in result:
            r=str(i)
            uno=int(r)
        print("got uno")
    else:
        print("error")
    
    cursor.execute("INSERT INTO reminder (U_no,Rtitle,Rdate,Rtime,Rpriority,status) VALUES (%s, %s, %s,%s,%s,%s)", (uno, title, date,time,pr,"active"))
    mydb.commit()
    print("out create reminder")
    print("created")
    remind()
    backtoscreen3()
    

def backtoscreen3 ():
    title_lable.place_forget()
    date_lable.place_forget()
    time_lable.place_forget()
    priority_lable.place_forget()
    cal.place_forget()
    title_input.place_forget()
    time_input.place_forget()
    priority.place_forget()
    ok_btn.place_forget()
    reminderselect_lable.place_forget()
    reminderselect_input.place_forget()
    content_lable.place_forget()
    slection_dropdown.place_forget()
    newvalue_input.place_forget()
    newvalue_lable.place_forget()
    update_btn.place_forget()
    back_btn.place_forget()
    history_btn.place_forget()
    tabview.place_forget()
    create_btn.place(x=235,y=186)
    view_btn.place(x=235,y=286)
    exit_btn.place(x=135,y=200)
    updates_btn.place(x=235,y=386)





def remind():
    print("in remind")
    today = datetime.today()
    today=today.strftime("%Y-%m-%d")
    print(today)

    cursor.execute("SELECT U_no FROM user WHERE name = %s AND password = %s", (user_input.get(),pass_input.get()))
    result = cursor.fetchone()
    if result:
        for i in result:
            r=str(i)
            uno=int(r)
            print("got uno")
    else:
        print("error")
    cursor.execute("SELECT Rtitle FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,today,"active"))
    msg = cursor.fetchone()
    if msg:
        for i in msg:
            msg=str(i)
            print("got msg")
            
    else:
        print("error")

    #notification.notify(title="Remind_IT",message=msg,app_name="Remind_IT",timeout=20,ticker="hi")
    print("out remind")

    print("in data")
    #cursor.execute("use remind_it")
    today = datetime.today()
    today=today.strftime("%Y-%m-%d")
    uno=0
    cursor.execute("SELECT U_no FROM user WHERE name = %s AND password = %s", (user_input.get(),pass_input.get()))
    result = cursor.fetchone()
    if result:
        for i in result:
            r=str(i)
            uno=int(r)
            print("got uno")
            
    else:
        print("error")
    cursor.execute("SELECT Rtime FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,today,"active"))
    remindtime = cursor.fetchone()
    if remindtime:
        for i in remindtime:
            remindtime=str(i)
            print(remindtime)

            print("got remindtime")
            
    else:
        print("error")

    cursor.execute("SELECT Rdate FROM reminder WHERE U_no = %s AND Rtime= %s AND status = %s",(uno,remindtime,"active"))
    rdate = cursor.fetchone()
    if rdate :
        for i in rdate:
            rdate=str(i)
            print("got rdate")
            
    else:
        print("error")

    cursor.execute("SELECT Rpriority FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,rdate,"active"))
    rpriority = cursor.fetchone()
    if rpriority:
        for i in rpriority:
            rpriority=str(i)
            print("got priority")
            
    else:
        print("error")

    cursor.execute("SELECT status FROM reminder WHERE U_no = %s AND Rdate= %s AND Rtime = %s",(uno,rdate,remindtime))
    status = cursor.fetchone()
    if status:
        for i in status:
            status=str(i)
            print("got status")
            
    else:
        print("error")
    
    print("out data")
    today = datetime.today()
    today=today.strftime("%Y-%m-%d")
    remindertime=remindtime #datetime.strptime(,"%H:%M:%S")

    count=cursor.rowcount
    print(count)

    while count >=0 and status=="active" :
        print("in while record",count)
        now = datetime.now()
        current_time = now.strftime("%H:%M:%S")
        print(current_time,"   ",remindertime)
        if remindertime==current_time and rdate==today and rpriority =="High" :
            #schedule.run_pending()
            notification.notify(title="Remind_IT",message=msg,app_name="Remind_IT",timeout=20,ticker="hi")
            cursor.execute("UPDATE reminder SET status =%s WHERE Rtitle=%s and Rtime=%s and status=%s",("done",msg,remindertime,"done"))
            mydb.commit()
            print("in first if")
            break
        count-=1   
        print("out while")


def showreminder():
    today = datetime.today()
    today=today.strftime("%Y-%m-%d")
    uno=0
    
    cursor.execute("SELECT U_no FROM user WHERE name = %s AND password = %s", (user_input.get(),pass_input.get()))
    result = cursor.fetchone()
    if result:
        for i in result:
            r=str(i)
            uno=int(r)
            print("got uno")
            
    else:
        print("error")
    cursor.execute("SELECT Rtitle FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,today,"active"))
    msg = cursor.fetchone()
    if msg:
        for i in msg:
            msg=str(i)
            print("got msg")
            
    else:
        print("error")
    cursor.execute("SELECT Rtime FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,today,"active"))
    remindtime = cursor.fetchone()
    if remindtime:
        for i in remindtime:
            remindtime=str(i)
            print(remindtime)
            print("got remindtime")
            
    else:
        print("error")

    cursor.execute("SELECT Rdate FROM reminder WHERE U_no = %s AND Rtime= %s AND status = %s",(uno,remindtime,"active"))
    rdate = cursor.fetchone()
    if rdate :
        for i in rdate:
            rdate=str(i)
            print("got rdate")
            
    else:
        print("error")

    cursor.execute("SELECT Rpriority FROM reminder WHERE U_no = %s AND Rdate= %s AND status = %s",(uno,rdate,"active"))
    rpriority = cursor.fetchone()
    if rpriority:
        for i in rpriority:
            rpriority=str(i)
            print("got priority")
            
    else:
        print("error")

    cursor.execute("SELECT status FROM reminder WHERE U_no = %s AND Rdate= %s AND Rtime = %s",(uno,rdate,remindtime))
    status = cursor.fetchone()
    if status:
        for i in status:
            status=str(i)
            print("got status")
            
    else:
        print("error")
    
    print("out data")
    today = datetime.today()
    today=today.strftime("%Y-%m-%d")
    remindertime=remindtime #datetime.strptime(,"%H:%M:%S")

    count=cursor.rowcount
    print(count)

    while count >=0 and status=="active" :
        print("in while record",count)
        now = datetime.now()
        current_time = now.strftime("%H:%M:%S")
        print(current_time,"   ",remindertime)
        if remindertime==current_time and rdate==today and rpriority =="High" :
            #schedule.run_pending()
            notification.notify(title="Remind_IT",message=msg,app_name="Remind_IT",timeout=20,ticker="hi")
            cursor.execute("UPDATE reminder SET status =%s WHERE Rtitle=%s and Rtime=%s and status=%s",("done",msg,remindertime,"done"))
            mydb.commit()
            print("in first if")
            break
        count-=1   
        print("out while")






def screen4 ():
    create_btn.place_forget()
    view_btn.place_forget()
    exit_btn.place_forget()
    title_lable.place(x=50,y=110)
    date_lable.place(x=50,y=130)
    time_lable.place(x=50,y=150)
    priority_lable.place(x=50,y=170)
    title_input.place(x=456,y=169)
    #date_input.place(x=456,y=196)
    time_input.place(x=456,y=218)
    priority.place(x=456,y=266)
    cal.place(x=456,y=366)
    #t.place(x=456,y=388)
    ok_btn.place(x=222,y=343)

dropdown_var=ctk.StringVar(value="Rtitle")
reminder_selct_var=ctk.StringVar()
newvalue_input_var=ctk.StringVar()
#tablepreview = ctk.CTkTextbox(window)
slection_dropdown = ctk.CTkComboBox(master=window,values=["Rtitle", "Rdate","Rtime"],variable=dropdown_var)
reminderselect_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=reminder_selct_var)
newvalue_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=newvalue_input_var)
reminderselect_lable=ctk.CTkLabel(master=window, text="Select reminder title to change :-", font=("Arial",25),)
content_lable=ctk.CTkLabel(master=window, text="Select what field to change :-", font=("Arial",25),)
newvalue_lable=ctk.CTkLabel(master=window, text="Enter value to change :-", font=("Arial",25),)

def screen5 ():
    create_btn.place_forget()
    view_btn.place_forget()
    exit_btn.place_forget()
    title_lable.place_forget()
    date_lable.place_forget()
    time_lable.place_forget()
    priority_lable.place_forget()
    cal.place_forget()
    title_input.place_forget()
    time_input.place_forget()
    priority.place_forget()
    ok_btn.place_forget()
    updates_btn.place_forget()
    #tablepreview.place(x=200,y=200)
    reminderselect_lable.place(x=50,y=110)
    content_lable.place(x=50,y=150)
    newvalue_lable.place(x=50,y=190)
    reminderselect_input.place(x=400,y=110)
    slection_dropdown.place(x=400,y=150)
    newvalue_input.place(x=400,y=190)
    update_btn.place(x=400,y=250)


    '''count=cursor.rowcount
    #tablepreview.grid(row=count+1, column=6)
    #tablepreview.insert('0.0',text="U_no Rtitle Rdate Rtime Rpriority status")
    uno=0
    cursor.execute("SELECT U_no FROM user WHERE name = %s AND password = %s", (user_input.get(),pass_input.get()))
    result = cursor.fetchone()
    if result:
        for i in result:
            r=str(i)
            uno=int(r)
            print("got uno")
            
    else:
        print("error")
    cursor.execute("SELECT * FROM reminder WHERE U_no = %s AND status=%s ",(uno,"active"))
    value = cursor.fetchall()
    if value:
        a=0.1
        for i in value:
            a=str(a)
            value=str(value)
            tablepreview.insert(a,value)
            a=float(a)
            a=a+0.1
            print("done")
            
    else:
        print("error")'''
    
def updatemsg():
    if dropdown_var.get()=="Rtitle":
        print("in title")
        cursor.execute("UPDATE reminder SET Rtitle =%s WHERE Rtitle=%s AND status=%s",(newvalue_input.get(),reminderselect_input.get(),"active"))
        mydb.commit()
        backtoscreen3()
        print("done")
    elif dropdown_var.get()=="Rdate":
        print("in date")
        today = datetime.today()
        today=today.strftime("%Y-%m-%d")
        print(today)
        if today<=newvalue_input.get() :
            print("in if")
            date=newvalue_input.get()
            print(date)
            cursor.execute("UPDATE reminder SET Rdate =%s WHERE Rtitle=%s AND status=%s",(date,reminderselect_input.get(),"active"))
            mydb.commit()
            backtoscreen3()
        print("out if")
        print("done")
    elif dropdown_var.get()=="Rtime":
        now = datetime.now()
        current_time = now.strftime("%H:%M:%S")
        print("in time")
        if current_time<=newvalue_input.get():
            print("in if")
            cursor.execute("UPDATE reminder SET Rtime =%s WHERE Rtitle=%s AND status=%s",(newvalue_input.get(),reminderselect_input.get(),"active"))
            mydb.commit()
            backtoscreen3()
        print("out if")
        print("done")
    else:
        print("error")




update_btn = ctk.CTkButton(window, text="updatea", font=("Arial", 14, "bold"), command=updatemsg )
ok_btn = ctk.CTkButton(window, text="create", font=("Arial", 14, "bold"), command= create_reminder)
'''def motion(event):
    x, y = event.x, event.y
    print('{}, {}'.format(x, y))

window.bind('<Motion>', motion)'''
search_var=ctk.StringVar()
search_dropdown_var=ctk.StringVar(value="All")
search_input=ctk.CTkEntry(window,font=("Arial",22),textvariable=search_var)
search_codition= ctk.CTkComboBox(master=window,values=["All", "Rdate","U_no","Rtime","Rpriority","status"],variable=dropdown_var)
tabview = ctk.CTkTabview(window)


def view_reminder():
    create_btn.place_forget()
    view_btn.place_forget()
    exit_btn.place_forget()
    updates_btn.place_forget()
    tabview.place(x=80,y=80)
    history_btn.place(x=90,y=10)


    
    tab_1 = tabview.add("Active Reminders")
    tab_2 = tabview.add("Done Reminders")
    tabview.set("Active Reminders")
    trv = ttk.Treeview(tab_1, selectmode ='browse')
    trv.grid(row=1,column=1,padx=20,pady=20)
    trv["columns"] = ("1", "2", "3","4","5","6")
    trv['show'] = 'headings'
    trv.column("1", width = 100, anchor ='c')
    trv.column("2", width = 100, anchor ='c')
    trv.column("3", width = 100, anchor ='c')
    trv.column("4", width = 100, anchor ='c')
    trv.column("5", width = 100, anchor ='c')
    trv.column("6", width = 100, anchor ='c')
    trv.heading("1", text ="User No.")
    trv.heading("2", text ="Reminder Title")
    trv.heading("3", text ="Reminder Date")
    trv.heading("4", text ="Reminder Time")  
    trv.heading("5", text ="Reminder Priority")
    trv.heading("6", text ="Status")

    cursor.execute("select * from reminder where status=%s",("active",))
    result=cursor.fetchall()
    for dt in result: 
        trv.insert("", 'end',iid=dt[0], text=dt[0],values =(dt[0],dt[1],dt[2],dt[3],dt[4],dt[5]))


    trv2 = ttk.Treeview(tab_2, selectmode ='browse')
    trv2.grid(row=1,column=1,padx=20,pady=20)
    trv2["columns"] = ("1", "2", "3","4","5","6")
    trv2['show'] = 'headings'
    trv2.column("1", width = 100, anchor ='c')
    trv2.column("2", width = 100, anchor ='c')
    trv2.column("3", width = 100, anchor ='c')
    trv2.column("4", width = 100, anchor ='c')
    trv2.column("5", width = 100, anchor ='c')
    trv2.column("6", width = 100, anchor ='c')
    trv2.heading("1", text ="User No.")
    trv2.heading("2", text ="Reminder Title")
    trv2.heading("3", text ="Reminder Date")
    trv2.heading("4", text ="Reminder Time")  
    trv2.heading("5", text ="Reminder Priority")
    trv2.heading("6", text ="Status")

    cursor.execute("select * from reminder where status=%s",("done",))
    data=cursor.fetchall()
    for dt in data: 
        trv.insert("", 'end',iid=dt[0], text=dt[0],values =(dt[0],dt[1],dt[2],dt[3],dt[4],dt[5]))
def historymsg():
    tabview.place_forget()
    back_btn.place(x=300,y=200)
    trv = ttk.Treeview(window, selectmode ='browse')
    trv.grid(row=1,column=1,padx=200,pady=200)
    trv["columns"] = ("1", "2", "3","4","5","6")
    trv['show'] = 'headings'
    trv.column("1", width = 100, anchor ='c')
    trv.column("2", width = 100, anchor ='c')
    trv.column("3", width = 100, anchor ='c')
    trv.column("4", width = 100, anchor ='c')
    trv.column("5", width = 100, anchor ='c')
    trv.column("6", width = 100, anchor ='c')
    trv.heading("1", text ="User No.")
    trv.heading("2", text ="Reminder Title")
    trv.heading("3", text ="Reminder Date")
    trv.heading("4", text ="Reminder Time")  
    trv.heading("5", text ="Reminder Priority")
    trv.heading("6", text ="Status")

    cursor.execute("select * from reminder ",)
    result=cursor.fetchall()
    for dt in result: 
        trv.insert("", 'end',iid=dt[0], text=dt[0],values =(dt[0],dt[1],dt[2],dt[3],dt[4],dt[5]))
back_btn=ctk.CTkButton(window, text="back", font=("Arial", 14, "bold"), command= backtoscreen3)
history_btn=ctk.CTkButton(window, text="History", font=("Arial", 14, "bold"), command= historymsg)
def q():
    quit()
create_btn=ctk.CTkButton(window, text="create", font=("Arial", 14, "bold"), command= screen4)
updates_btn=ctk.CTkButton(window, text="update", font=("Arial", 14, "bold"), command= screen5)
view_btn=ctk.CTkButton(window, text="view", font=("Arial", 14, "bold"), command= view_reminder)
exit_btn =ctk.CTkButton(window, text="➡️", font=("Arial", 14, "bold"), command= q)



def screen2():
    label_title.place_forget()
    login_button.place_forget()
    head_lable.place(x=255, y=1)
    login_label.place(x=266, y=82)
    uid_label.place(x=126,y=152)
    pass_label.place(x=126,y=225)
    user_input.place(x=326,y=152)
    pass_input.place(x=326,y=242)
    lng_button.place(x=426,y=342)
login_button = ctk.CTkButton(window, text="enter", font=("Arial", 14, "bold"), command= screen2)
lng_button = ctk.CTkButton(window, text="enter", font=("Arial", 14, "bold"), command= login)

screen1()
window.mainloop()


#def data ():
    
    #return remindtime,rdate,rpriority,status

#remindtime,rdate,rpriority,status = data()

window.mainloop()

Now I want to run showreminder repeatedly in the background without affecting the GUI and it must run on Windows 10/11.

I tried to use the schedule module but it did not get executed,
and I tried to put the whole code in while loop. It did work but other function where not usable until the reminder came.

Asked By: YASHAS R NAIR

||

Answers:

Whenever you want to perform two or more operations in parallel use threading module

import threading

def showreminder():
    # define your function

def showreminder_threaded():
    thread = threading.Thread(target = showreminder())
    thread.start()

Instead of calling showreminder() call showreminder_threaded(), then it will run parallelly

Answered By: Sunny Kumar

After reading all of your suggestion and tinkering around I found that this code made helped what I want to accomplish

def call_showreminders():
     current_time = datetime.now().strftime("%S")
     if current_time == "00":
        showreminder()
        window.after(1000, call_showreminders)  # call call_showreminders every second
window.after(1000, call_showreminders)
window.mainloop()
Answered By: YASHAS R NAIR