Python Tkinter:如何从主页面访问父类的用户数据字典
我来帮你搞定这个问题,咱们一步步拆解问题并修复:
1. 解决KeyError的核心问题
你在登录成功后把用户年龄存在了self.controller.userInfo['age'],但在主页面的打印方法里却错误地访问self.controller.fromDB['age']——fromDB只是登录页面里的局部变量,根本没在FirstApp类里定义过,这就是KeyError的直接原因。咱们要统一用userInfo这个controller里的变量来存储用户数据。
2. 修复SQL语句的语法错误
你的SQL查询里多了个逗号,会导致数据库执行报错:
-- 错误写法:age后面多了逗号 Select COUNT(id) AS count,age, from users Where username = %s AND password = %s
改成下面的正确写法:
Select COUNT(id) AS count, age from users Where username = %s AND password = %s
3. 处理游标返回值的类型问题
如果你的数据库游标默认返回元组而不是字典,那fromDB[0]['age']这种字典式访问会失败。可以两种方式处理:
- 要么改用索引访问:
fromDB[0][1](因为count是第一个字段,age是第二个) - 要么把游标设置为字典游标(比如MySQL的
cursorclass=MySQLdb.cursors.DictCursor),这样就能用键名访问了。
4. 正确设置滑块的默认值
你现在在主页面初始化时把滑块固定设为7,应该在登录成功后,把滑块值更新为用户的实际年龄。可以给MainPage加一个更新滑块的方法,或者在切换页面时触发更新。
下面是修改后的完整代码,我标注了所有修改的地方:
import tkinter as tk import hashlib # 假设你的myconnutils是正确导入的 import myconnutils class FirstApp(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.frames = {} # 补上漏初始化的frames字典 container = tk.Frame(self) container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) self.userInfo = {} self.connection = myconnutils.getConnection() # 如果用的是MySQL,建议设置为字典游标,方便用键名访问 # self.cursor = self.connection.cursor(cursorclass=myconnutils.cursors.DictCursor) self.cursor = self.connection.cursor() for F in (LoginPage, MainPage): page_name = F.__name__ frame = F(parent=container, controller=self) self.frames[page_name] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame("LoginPage") def __del__(self): if hasattr(self, 'connection') and self.connection.is_connected(): self.connection.close() def show_frame(self, page_name): frame = self.frames[page_name] # 切换到主页面时自动更新滑块值 if page_name == "MainPage" and 'age' in self.userInfo: frame.update_slider(self.userInfo['age']) frame.tkraise() class LoginPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller self.cursor= self.controller.cursor label2 = tk.Label(self, text="Login:") label2.place(x=310, y=90, in_=self) self.e1 = tk.Entry(self) self.e1.place(x=370, y=90, in_=self) label3 = tk.Label(self, text="Password:") label3.place(x=310, y=120, in_=self) self.e2 = tk.Entry(self, show="*") self.e2.place(x=370, y=120, in_=self) button1 = tk.Button(self, text="Login", command=self._login_btn_clicked,width = 25) button1.place(x=310, y=150, in_=self) def _login_btn_clicked(self): username = self.e1.get() password = self.e2.get() hash = hashlib.sha512() hash.update(('%s%s' % ('salt', password)).encode('utf-8')) password_hash = hash.hexdigest() # 修复SQL的逗号问题 sql = "Select COUNT(id) AS count, age from users Where username = %s AND password = %s" self.cursor.execute(sql, (username,password_hash)) fromDB = self.cursor.fetchall() # 普通游标用索引访问,字典游标可以用fromDB[0]['age'] if fromDB[0][0] > 0: # 存储用户数据到controller的userInfo self.controller.userInfo['age'] = fromDB[0][1] # 可以顺便存储其他用户数据 # self.controller.userInfo['username'] = username self.controller.show_frame("MainPage") class MainPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="Main Page") label.pack() self.w = tk.Scale(self, from_=0, to=200, orient='horizontal') self.w.pack() button = tk.Button(self, text="Print", command=self.funcPrint) button.pack() # 新增更新滑块的方法 def update_slider(self, age): self.w.set(age) def funcPrint(self): ee=self.w.get() print(ee) # 正确访问controller里的userInfo print(self.controller.userInfo['age']) if __name__ == "__main__": app = FirstApp() app.geometry('800x600') # 调整窗口大小,避免控件显示不全 app.mainloop()
额外注意点
- 补上了你之前漏初始化的
self.frames = {},不然程序启动就会报错 - 关闭连接时加了判断,避免连接已关闭时报错
- 调整了窗口尺寸,原来的300x300会导致登录页面控件被截断
内容的提问来源于stack exchange,提问作者duli
相关产品推荐
相关产品推荐

