This project is an Inventory Management system. I am still a beginner My code has a lot of issues, which I know. Right now I am struggling with using two different classes together. (I also think I don't need to use classes if I can't organizing my code which is why I opted for it in the first place)
from tkinter import *
import customtkinter as ctk
from CTkMessagebox import CTkMessagebox
import mysql.connector
class Inventory():
conn = mysql.connector.connect(host='localhost', user='root', password='1810', database='inventory')
csr = conn.cursor()
Logged_in = False
#Initialization of onject variables
def __init__(self):
#Inheritance
super().__init__()
self.login = ctk.CTk()
self.login.title('Inventory Management')
self.login.geometry("800x600+10+10")
self.login.resizable(False,False)
#Username input
self.usrname_label = ctk.CTkLabel(self.login, text="Username--", font=("Helvetica", 13))
self.usrname_label.place(x=145,y=110)
self.usrnm_input = ctk.CTkEntry(self.login, bg_color='white', fg_color='#AFE8DF', border_width=5)
self.usrnm_input.place(x=230, y=110)
#password input
self.pswd_label = ctk.CTkLabel(self.login, text="Password--", font=("Helvetica", 13))
self.pswd_label.place(x=145,y=150)
self.pswd_input = ctk.CTkEntry(self.login, bg_color='white', fg_color='#AFE8DF', border_width=5, show='*')
self.pswd_input.place(x=230, y=150)
#buttons
self.login_btn = ctk.CTkButton(self.login, text="LOGIN", bg_color='white', fg_color='blue', command= self.check )
self.login_btn.place(x=230, y=200)
self.welcm= Label(self.login, text="Welcome to Inventory Management", fg='#E6A405', font=("Helvetica", 25))
self.welcm.place(x=140, y=40)
self.fgt_btn = ctk.CTkButton(self.login, text="Forgot Password",bg_color='#00A7E5', fg_color='#00081F', command = self.forgot_passward )
self.fgt_btn.place(x=280, y=400)
self.sin_up = ctk.CTkButton(self.login, text="New User?", bg_color='#00A7E5', fg_color='#00081F', command = self.sign_up )
self.sin_up.place(x=430, y=400)
#Looping the login window
self.login.mainloop()
#to check login details
def check(self):
username = self.usrnm_input.get().strip()
pswd = self.pswd_input.get()
if username == "":
no_user = CTkMessagebox(
title="Credentials Error !",
message="Pleaase enter login details",
option_1="Retry",
icon = "cancel"
)
else:
Inventory.csr.execute("SELECT * FROM Users WHERE Username = '{}'".format(username))
user = Inventory.csr.fetchone()
if user:
if pswd in user:
msg = CTkMessagebox(title = "Login", message="Login Successful !", option_1 = "Ok")
if msg.get() == "Ok":
Inventory.Logged_in = True
self.login.withdraw()
self.usrnm_input.delete(0, END)
self.pswd_input.delete(0, END)
self.start_menu()
else:
inc_pswd = CTkMessagebox(
title="Credentials Error !",
message="Wrong password",
option_1="Retry",
icon = "cancel"
)
else:
self.inc_usr()
#For Forgot Password Page
def forgot_passward(self):
self.fgt_window = ctk.CTk()
self.fgt_window.geometry('800x600')
self.fgt_window.title('Forgot Password')
self.funam_lbl = ctk.CTkLabel(self.fgt_window, text="Username--", font=("Helvetica", 13))
self.funam_lbl.place(x=165,y=110)
self.funam_txt = ctk.CTkEntry(self.fgt_window, border_width=5, fg_color='#AFE8DF')
self.funam_txt.place(x=250, y=110)
self.fnam_lbl = ctk.CTkLabel(self.fgt_window, text="Name--", font=("Helvetica", 13))
self.fnam_lbl.place(x=165,y=75)
self.fnam_txt = ctk.CTkEntry(self.fgt_window, border_width=5, fg_color='#AFE8DF')
self.fnam_txt.place(x=250, y=75)
self.fsk_lbl = ctk.CTkLabel(self.fgt_window, text="Security Key--", font=("Helvetica", 13))
self.fsk_lbl.place(x=165,y=145)
self.fsk_txt = ctk.CTkEntry(self.fgt_window, border_width=5, fg_color='#AFE8DF')
self.fsk_txt.place(x=250, y=145)
self.fnxt_btn = ctk.CTkButton(self.fgt_window, text="Next",bg_color='#00A7E5', fg_color='#00081F', command = self.forgot_pswd_check)
self.fnxt_btn.place(x=252, y=200)
self.fgt_window.mainloop()
#For checking details for forgot password window
def forgot_pswd_check(self):
username = self.funam_txt.get().strip()
s_key = int(self.fsk_txt.get().strip())
name = self.fnam_txt.get().strip()
if username == "" or s_key == "" or name == "":
no_user = CTkMessagebox(
title="Credentials Error !",
message="Pleaase enter login details",
option_1="Retry",
icon = "cancel"
)
user = False
else:
Inventory.csr.execute("SELECT * FROM Users WHERE Username = '{}'".format(username))
user = Inventory.csr.fetchone()
print("\n\n\n"+str(user)+"\n\n\n")
if user:
if (name == user[1]) and (s_key == user[3]):
self.frgt_pswd_user = user
self.cre_vrf()
elif s_key not in user:
self.inc_sk()
else:
msg = CTkMessagebox(
title="Inncorrect Credentials!", message="Incorrect Name",
option_1="Ok"
)
else:
self.inc_usr()
#Verification of credentials
#After checking from database returns the message after
def cre_vrf(self):
cr_vrf = CTkMessagebox(title="Change Password", message="Credentials Verified !", option_1="Cont...")
if cr_vrf.get()=="Cont...":
self.fgt_window.destroy()
self.Paswd_cng()
#cont... button takes to change password page
#To change password
def Paswd_cng(self):
self.pswd_cng = ctk.CTk()
self.pswd_cng.geometry('600x600')
self.pswd_cng.title('Change Password')
self.fpw_lbl = ctk.CTkLabel(self.pswd_cng, text="Password--", font=("Helvetica", 13))
self.fpw_lbl.place(x=125,y=145)
self.new_pswd_entry = ctk.CTkEntry(self.pswd_cng, border_width=5, fg_color='#AFE8DF')
self.new_pswd_entry.place(x=250, y=145)
self.retype_pswd = ctk.CTkLabel(self.pswd_cng, text="Retype Password--", font=("Helvetica", 13))
self.retype_pswd.place(x=125,y=180)
self.retype_pswd_entry = ctk.CTkEntry(self.pswd_cng, border_width=5, fg_color='#AFE8DF')
self.retype_pswd_entry.place(x=250, y=180)
self.fpw_btn = ctk.CTkButton(self.pswd_cng, text="Cont...",bg_color='#00A7E5', fg_color='#00081F', command=self.cng_psd_prcs)
self.fpw_btn.place(x=250, y=230)
self.pswd_cng.mainloop()
def cng_psd_prcs(self):
psd = self.new_pswd_entry.get()
if psd == self.retype_pswd_entry.get():
Inventory.csr.execute("UPDATE Users SET pswd = '{}' WHERE Username = '{}'".format(psd, self.frgt_pswd_user[0]))
Inventory.conn.commit()
self.Paswd_ssfl()
else:
msg = CTkMessagebox(title = "Retype passwords", cancel = "Passwords Do not match", option_1="Ok")
#To notify password change successful
def Paswd_ssfl(self):
paswd_sf = CTkMessagebox(title="Password Change!", message="Password Change successful, Please",option_1="Login")
if paswd_sf.get() == "Login":
self.pswd_cng.destroy()
#For Sign Up page
def sign_up(self):
self.sin_up = ctk.CTk()
self.sin_up.geometry('600x600')
self.sin_up.title('Sign Up')
self.sunam_lbl = ctk.CTkLabel(self.sin_up, text="Username--", font=("Helvetica", 13))
self.sunam_lbl.place(x=125,y=110)
self.sunam_txt = ctk.CTkEntry(self.sin_up, border_width=5, fg_color='#AFE8DF')
self.sunam_txt.place(x=250, y=110)
self.snam_lbl = ctk.CTkLabel(self.sin_up, text="Name--", font=("Helvetica", 13))
self.snam_lbl.place(x=125,y=75)
self.snam_txt = ctk.CTkEntry(self.sin_up, border_width=5, fg_color='#AFE8DF')
self.snam_txt.place(x=250, y=75)
self.spw_lbl = ctk.CTkLabel(self.sin_up, text="Password--", font=("Helvetica", 13))
self.spw_lbl.place(x=125,y=145)
self.spw_txt = ctk.CTkEntry(self.sin_up, border_width=5, fg_color='#AFE8DF')
self.spw_txt.place(x=250, y=145)
self.srpw_lbl = ctk.CTkLabel(self.sin_up, text="Retype Password--", font=("Helvetica", 13))
self.srpw_lbl.place(x=125,y=180)
self.srpw_txt = ctk.CTkEntry(self.sin_up, border_width=5, fg_color='#AFE8DF')
self.srpw_txt.place(x=250, y=180)
self.snxt_btn = ctk.CTkButton(self.sin_up, text="Next",bg_color='#00A7E5', fg_color='#00081F', command=self.cre_svd )
self.snxt_btn.place(x=252, y=240)
self.sin_up.mainloop()
#For credentials Saving
def cre_svd(self):
cre_svd = CTkMessagebox(title="Credentials Saved !", message="User data has been recorder", option_1="Cont...")
#We need to connect this message box to cont_sinup page
#For Continue Button, Sign Up page, To show security key
def cont_sinup(self):
cont_su = ctk.CTk()
cont_su.geometry('600x600')
cont_su.title('Confidential--Security Key')
sk1_lbl= Label(cont_su, text="Please Save and Remember your Security Key", fg='#E6A405', font=("Helvetica", 25))
sk1_lbl.place(x=55, y=40)
#How to display random security key
sk2_lbl= Label(cont_su, text="This Security Key will not be shown again", fg='#E6A405', font=("Helvetica", 16))
sk2_lbl.place(x=180, y=500)
sk_btn=ctk.CTkButton(cont_su, text="Cont..",bg_color='#00A7E5', fg_color='#00081F', command=self.sinup_cnfrm)
sk_btn.place(x=248, y=440)
cont_su.mainloop()
#For Sign Up Confirmation:
def sinup_cnfrm():
siup_con = CTkMessagebox(title="Sign Up", message="Sign Up Confirmed, Please Restart the Application",option_1="Done")
#For Incorrect Security Key
#For Forgot Password Page
def inc_sk(self):
# Show some retry/cancel warnings
incsk = CTkMessagebox(title="Inncorrect Credentials!", message="Security Code Inccorect",
option_1="Cancel", option_2="Retry")
if incsk.get()=='Retry':
show_Warning("Please try again")
#Incorrect User
#For Forgot Password Page
def inc_usr(self):
incusr = CTkMessagebox(title="Inncorrect Credentials!", message="User Not Found",
option_1="Ok")
#For Menu
def start_menu(self):
self.menu = Main()
self.menu.title('Inventory Menu')
self.menu.geometry("600x600+10+10")
self.menu.resizable(False,False)
self.menu.protocol("WM_DELETE_WINDOW", self.on_closing)
self.menu.mainloop()
def on_closing(self):
msg = CTkMessagebox(title="o", message="Are you sure?", option_2="yes", option_1="no")
if msg.get() == "yes":
self.login.deiconify()
self.menu.destroy()
class Main(ctk.CTk):
def __init__(self):
self.geometry("1000x800+50+50")
self.title("Inventory Manager")
if __name__ == "__main__":
App = Inventory()
After a successful Login, the login window should minimise using self.login.withdraw()
and a new window of the main application should open. On closing that window, the login window should appear again.
The problem is that calling self.menu = Main()
creates an infinite recursion loop somehow.
This obviously does not happen with the following block of code in place
def start_menu(self):
self.menu = ctk.CTk()
self.menu.title('Inventory Menu')
self.menu.geometry("600x600+10+10")
self.menu.resizable(False,False)
self.menu.protocol("WM_DELETE_WINDOW", self.on_closing)
self.menu.mainloop()
But this would make the code far more cluttered which makes using classes futile.
super().__init__()
insideMain.__init__()
.