Tkinter面向对象开发三类核心技术疑问解析
Tkinter OOP实践中的三个问题解惑
我正在开发一款儿童字母学习的Tkinter小游戏,遵循OOP最佳实践时遇到三个问题,附上代码并请求专业解惑:
import tkinter as tk class MainApplication(tk.Frame): def __init__(self, master): self.master = master tk.Frame.__init__(self, self.master) # or super().__init__(self.master)? self.configure_gui() self.create_widgets() def configure_gui(self): self.master.title('Example') self.master.geometry('500x500') self.master.minsize(100, 100) self.master.columnconfigure([0, 1], minsize=50, weight=1) self.master.rowconfigure([0, 1], minsize=50, weight=1) # self.master.resizable(False, False) def create_widgets(self): # Frame that will contain the big letter self.letterbox = tk.Frame(self.master, bg='red', width=200, height=200) self.letterbox.grid(row=0, column=0, sticky='nsew') ... # Frame that contains the 3 animal pictures self.animalbox = tk.Frame(self.master, bg='yellow') self.animalbox.rowconfigure(0, weight=1) self.animalbox.columnconfigure([0, 1, 2], weight=1) self.animalbox.grid(row=1, column=0, sticky='nsew') self.animalbox_left = tk.Button(self.animalbox, text='left animal') self.animalbox_left.grid(row=0, column=0, padx=10, pady=10, ipady=10) self.animalbox_middle = tk.Button(self.animalbox, text='middle animal') self.animalbox_middle.grid(row=0, column=1, padx=10, pady=10, ipady=10) self.animalbox_right = tk.Button(self.animalbox, text='right animal') self.animalbox_right.grid(row=0, column=2, padx=10, pady=10, ipady=10) # Frame that contains the score and options self.scorebox = tk.Frame(self.master, bg='blue') self.scorebox.grid(row=0, column=1, rowspan=2, sticky='nsew') def main(): root = tk.Tk() MainApplication(root) root.mainloop() if __name__ == '__main__': main()
问题与解惑
1. 父类构造方法调用的参数差异
直接调用tk.Frame.__init__(self, self.master)需要传两个参数,而super().__init__(self.master)只传一个的原因:
- 直接调用父类的
__init__属于未绑定方法调用——父类构造方法没有和子类实例绑定,必须手动把当前实例self作为第一个参数传入,否则父类方法无法操作实例。 super()会返回一个绑定了当前子类实例的代理对象,调用它的__init__时,会自动把self作为第一个参数传递,所以只需要传入master即可。如果给super().__init__传两个参数,会触发参数数量不匹配的报错。
2. 部件master参数的差异
参考示例中部件可以传self作为master,而你的代码必须传self.master才能运行的原因:
你的MainApplication继承自tk.Frame,但没有将这个Frame本身布局到主窗口。正常做法是在__init__中调用self.pack()、self.grid()或self.place(),把当前Frame实例嵌入到master(主窗口)中。这样这个Frame就成为主窗口的子容器,后续创建的部件可以把self(当前Frame)作为master,成为它的子部件并正常显示。
你的代码里缺少这一步,所以如果部件的master传self,这个部件属于未被布局的Frame,自然无法显示;只有传self.master,让部件直接属于主窗口,才能在界面上看到。
3. main函数中是否需要赋值实例
不需要。MainApplication的实例会被主窗口root持有引用,只要root.mainloop()的事件循环在运行,这个实例就不会被Python的垃圾回收机制清理。不过如果后续需要在main()中操作这个实例(比如调用它的方法),则需要赋值给变量;如果只是启动程序,直接创建实例不赋值完全没问题。
内容的提问来源于stack exchange,提问作者Ranudar
相关产品推荐
相关产品推荐

