Python+MySQL库存管理系统类调用引发无限递归循环问题求助
Python+MySQL库存管理系统类调用引发无限递归循环问题求助
大家好,我是编程新手,正在开发一个基于Python+MySQL的库存管理系统,目前遇到了类调用导致的无限递归循环问题,想请各位大佬帮忙分析解决。
先说说我的核心需求:
- 登录成功后,调用
self.login.withdraw()隐藏登录窗口,然后打开主应用窗口 - 关闭主应用窗口时,重新显示登录窗口
现在的问题是,当我在start_menu方法里用self.menu = Main()创建主窗口实例时,会触发无限递归循环;但如果我不用自定义的Main类,而是直接创建ctk.CTk()实例(如下方注释的代码块),就能正常实现窗口切换,但这样代码会变得非常杂乱,我当初选择用类就是为了更好地组织代码,现在反而卡在这里了。
以下是我的完整代码:
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 object 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="Please 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="Please 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="Incorrect 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 recorded", 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(self): 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="Incorrect credentials!", message="Security code incorrect", 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="Incorrect 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="Quit", 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): super().__init__() self.geometry("1000x800+50+50") self.title("Inventory Manager") if __name__ == "__main__": App = Inventory()
我知道自己的代码还有不少其他问题(比如SQL语句存在注入风险,类变量的使用方式也不太规范),但现在最紧急的是解决这个无限递归的问题,先把窗口切换的逻辑跑通。麻烦各位帮忙看看问题出在哪里,该怎么修改?
备注:内容来源于stack exchange,提问作者Tarexino
相关产品推荐
相关产品推荐

