Python Tkinter传入root实现多窗口跳转时AttributeError问题排查
Tkinter传入root实现多窗口时的AttributeError问题
问题说明
尝试用Python Tkinter通过类实现主窗口打开子窗口的功能,采用传入root而非继承tk.Tk的方式。原继承tk.Tk的多窗口示例可正常运行,但改写为传入root的形式后,主窗口能正常打开,点击按钮打开子窗口时触发AttributeError,提示'App' object has no attribute 'tk'。
可正常运行的示例代码
import tkinter as tk from tkinter import ttk class Window(tk.Toplevel): def __init__(self, parent): super().__init__(parent) self.geometry('300x100') self.title('Toplevel Window') ttk.Button(self, text='Close', command=self.destroy).pack(expand=True) class App(tk.Tk): def __init__(self): super().__init__() self.geometry('300x200') self.title('Main Window') # 主窗口放置按钮 ttk.Button(self, text='打开窗口', command=self.open_window).pack(expand=True) def open_window(self): window = Window(self) window.grab_set() if __name__ == "__main__": app = App() app.mainloop()
改写后的错误代码
from tkinter import * from tkinter import ttk class Window(Toplevel): def __init__(self, parent): super().__init__(parent) self.geometry('300x100') self.title('Toplevel Window') ttk.Button(self, text='Close', command=self.destroy).pack(expand=True) class App(): def __init__(self, root): super().__init__() root.geometry('300x200') root.title('Main Window') # 主窗口放置按钮 ttk.Button(root, text='Open a window', command=self.open_window).pack(expand=True) def open_window(self): window = Window(self) window.grab_set() if __name__ == "__main__": root = Tk() App(root) root.mainloop()
报错信息
Traceback (most recent call last): File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__ return self.func(*args) ^^^^^^^^^^^^^^^^ File "c:\Users\User\Documents\Python\Python_Tutorial_net\Multiple_Windows_pass-in-Class.py", line 30, in open_window window = Window(self) ^^^^^^^^^^^^ File "c:\Users\User\Documents\Python\Python_Tutorial_net\Multiple_Windows_pass-in-Class.py", line 7, in __init__ super().__init__(parent) File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2678, in __init__ BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra) File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2623, in __init__ self._setup(master, cnf) File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2592, in _setup self.tk = master.tk ^^^^^^^^^ AttributeError: 'App' object has no attribute 'tk'
解决方案
错误原因
Window继承自Toplevel,创建实例时需要传入Tkinter窗口对象作为父组件。改写后的App是普通Python类,并非Tkinter窗口实例,传入self(App实例)不符合要求,导致Toplevel无法获取窗口对象的tk属性。
修改后的代码
from tkinter import * from tkinter import ttk class Window(Toplevel): def __init__(self, parent): super().__init__(parent) self.geometry('300x100') self.title('Toplevel Window') ttk.Button(self, text='Close', command=self.destroy).pack(expand=True) class App(): def __init__(self, root): self.root = root # 保存root窗口对象的引用 root.geometry('300x200') root.title('Main Window') ttk.Button(root, text='Open a window', command=self.open_window).pack(expand=True) def open_window(self): # 传入保存的root对象作为父组件 window = Window(self.root) window.grab_set() if __name__ == "__main__": root = Tk() App(root) root.mainloop()
关键修改点
- 在
App的__init__方法中添加self.root = root,保存Tkinter窗口对象的引用; - 移除
App中无意义的super().__init__()(因为App未继承任何父类); - 在
open_window方法中,将Window(self)改为Window(self.root),传入正确的Tkinter窗口对象作为父组件。
内容的提问来源于stack exchange,提问作者David Collins
相关产品推荐
相关产品推荐

