You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:53:45