Python Tkinter登录后多窗口间传递用户数据问题求助
解决Tkinter多窗口间共享用户字典的问题
你的问题根源在于用户字典discUserInfo被定义在StartPage类的实例中,只有StartPage能访问它,其他窗口(Window1、Window2)的实例根本没有这个属性,所以会抛出AttributeError。全局变量之所以失效,大概率是你没有在所有窗口中正确引用全局变量,而且全局变量本身也不是Tkinter多窗口共享数据的最佳实践。
我给你一个更优雅且可靠的解决方案:把共享的用户字典放在主应用控制器SampleApp中,因为所有页面都持有controller(也就是SampleApp的实例)的引用,这样所有窗口都能轻松访问这个字典。
修改步骤及完整代码
- 在
SampleApp的初始化方法中创建共享字典 - 在
StartPage的登录方法中,将用户数据写入控制器的字典 - 在其他窗口中,通过
self.controller.discUserInfo访问共享数据
import tkinter as tk from tkinter import font as tkfont class SampleApp(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic") # 在这里定义共享的用户字典,所有窗口都能通过controller访问 self.discUserInfo = {} 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.frames = {} for F in (StartPage, Window2, Window1): 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("StartPage") def show_frame(self, page_name): frame = self.frames[page_name] frame.tkraise() class StartPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="Start Page", font=controller.title_font) label.pack(pady=20) label2 = tk.Label(self, text="Login:") label2.pack() self.e1 = tk.Entry(self) self.e1.pack(pady=5) label3 = tk.Label(self, text="Password:") label3.pack() self.e2 = tk.Entry(self, show="*") self.e2.pack(pady=5) button1 = tk.Button(self, text="Login", command=self._login_btn_clicked, width=25) button1.pack(pady=10) def _login_btn_clicked(self): # 验证数据库逻辑(这里省略),然后将用户数据写入控制器的共享字典 self.controller.discUserInfo['name'] = 'Joe' self.controller.discUserInfo['userId'] = 1 self.controller.show_frame("Window1") class Window2(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="window 2", font=controller.title_font) label.pack(side="top", fill="x", pady=10) button1 = tk.Button(self, text="Test", command=self.onClick, width=42, bg="#C44041") button1.pack(pady=5) button3 = tk.Button(self, text="Back", command=lambda : controller.show_frame("Window1"), width=42, bg="#C44041") button3.pack(pady=5) def onClick(self): # 通过controller访问共享字典 print(self.controller.discUserInfo) class Window1(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="window 1", font=controller.title_font) label.pack(pady=20) button1 = tk.Button(self, text="Next", command=lambda: controller.show_frame("Window2"), width=42) button1.pack(pady=5) button2 = tk.Button(self, text="Test", command=self.getAlocationData, width=42) button2.pack(pady=5) def getAlocationData(self): # 通过controller访问共享字典 print(self.controller.discUserInfo) if __name__ == "__main__": app = SampleApp() app.geometry('{}x{}'.format(800, 650)) app.mainloop()
为什么这个方案有效?
SampleApp是整个应用的核心控制器,所有页面都持有它的引用(self.controller)- 把共享数据放在
SampleApp中,相当于所有页面共享同一个数据源,不管切换到哪个窗口,都能读取或修改这个字典 - 这种方式符合面向对象的设计思想,比全局变量更可控、更清晰,也避免了全局变量可能带来的作用域混乱问题
内容的提问来源于stack exchange,提问作者Andersi
相关产品推荐
相关产品推荐

