ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
### 8.4.1 将 GUI 应用程序封装成对象 GUI 编程的一个常用技术是将整个应用程序封装成一个类,在应用程序类中建立图形界 面并处理各种交互事件。具体来说,GUI 应用程序类应该首先创建一个主窗口,并在其中布 置所需的各种构件,然后再为各个构件编写事件处理程序(都是类的方法)。这种做法的好处 是:由于事件处理函数都定义为应用类的方法,而类的方法很自然地能访问类中的实例变量, 所以只要我们将界面中的各种构件也存储为实例变量,就能实现程序的处理代码与程序的图 形界面进行“无缝集成”。 在用 Tkinter 编程时,根据需要可以有多种方式来建立程序主窗口: (1)在应用程序类中创建自己的根窗口,即程序自成体系。代码大致形如: ``` class MyApp: def __init__ (self): root = Tk() b = Button(root,...) ... root.mainloop() app = MyApp() ``` (2)程序主窗口是程序类外部的某个窗口的子构件,该外部窗口在创建程序实例时作为 参数传递给构造器。例如: ``` class MyApp: def __init__ (self,master): f = Frame(master,...) b = Button(f,...) ... root = Tk() app = MyApp(root) root.mainloop() ``` (3)将应用程序类定义为框架构件类的子类,即程序就是窗口,窗口就是程序。如: ``` class MyApp(Frame): def __init__ (self): Frame. __init__ (self) # 先用父类的构造器进行初始化 b = Button(self,...) ... app = MyApp() app.mainloop() ``` 在应用程序类的设计中,如果一个构件具有“全局性”,即多个方法都要访问该元素,那 么就需用一个实例变量来存储(引用)这个构件,因为类的实例变量在所有类方法中都可访 问,而局部变量只在某一个方法中可见。 作为例子,我们定义一个应用程序类 MyApp,该程序的用户界面包括窗口、标签和按钮。 我们采用上述第一种方式,即程序创建自己的根窗口。根窗口和标签构件被存储为实例变量 self.root 和 self.t,以便 MyApp 类的所有方法都能引用它们;两个按钮则被存储为局部变量 b1 和 b2,这样在其他方法中是不能引用它们的。 【程序 8.11】myapp.py ``` from Tkinter import * class MyApp: def __init__ (self): self.root = Tk() self.root.title("My App") self.t = Label(self.root,text="Spam") self.t.pack() b1 = Button(self.root,text="Play",command=self.changeText) b2 = Button(self.root,text="Quit",command=self.root.quit) b1.pack() b2.pack() self.root.mainloop() self.root.destroy() def changeText(self): if self.t["text"] == "Spam": self.t["text"] = "Egg" else: self.t["text"] = "Spam" app = MyApp() ``` 程序 8.11 定义了类 MyApp,在其构造器 init__中首先创建根窗口 root,然后添加一个 标签和两个按钮。点击按钮 b1 时的回调函数是类 MyApp 中自定义的方法 changeText(功能 是改变标签的文本),点击 b2 时的回调函数是根窗口的内建方法 quit(退出事件循环)。标签 构件必须作为实例变量存储,因为 init 和 changeText 方法都要引用它;而根窗口和两个按 钮在本例中既可以作为实例变量存储,也可以作为局部变量存储。创建各构件并完成布局之 后进入事件循环,等待处理事件。 类只是一个定义,封装成类的应用程序如何执行呢?我们通常会为应用程序类定义一个 专门的启动方法 run,将来创建应用程序对象后通过调用对象的 run 方法来启动程序功能。本 例中 MyApp 程序对象 app 一经创建就自动进入程序主循环,这是因为我们将所有启动代码 包括 mainloop 都放在构造器 init__之中的缘故。程序启动后,点击 Play 按钮可以看到标签 内容在“Spam”和“Egg”之间切换。点击 Quit 按钮将退出事件循环,从而执行 init__的最 后一条语句 root.destroy 关闭根窗口①。 作为练习,读者可以用上述第二、三种方式来改写程序 8.11。