了解Python/tkinter的编码基础,主要使用一些简单的组件,包含:如何更好的创建组件、修改属性、pack、以及组件回调函数等;
tkinter程序的共同步骤:
1.从tkinter模块中加载一个/多个组件类
2.创建该组件类的实例为标签类
3.在父组件中打包新标签
4.调用主循环,显示窗口,同时开始tkinter的事件循环;
mainloop方法最后执行,将标签显示在屏幕,进入tkinter等待状态,准备响应用户发起的GUI事件。mainloop函数中,tkinter内部会监控这些事件,如键盘活动、鼠标单击等;
子组件如何部署在父组件?
举例:Label(None,text='Hello GUI world !!!').pack();
第一个参数是父组件对象,即:我们希望将新标签设置于其中。None,表示将新标签设置在该程序的默认顶层窗口;
第二个参数是标签配置选项。大多数组件的构造函数都能够接受多个关键字参数,对组件的颜色、尺寸、回调函数等进行具体设置
无参数的回调函数,组件在生成时,直接将command=函数名,即可成功实现回调函数;但是如果函数有参数,应该如何传参喃?要指导回调函数是不能直接加括号的,加括号就直接运行了,不会等待你触发事件才执行。
方式1:lambda匿名函数实现延迟调用
from tkinter import * #lambda匿名函数实现延迟调用 def handler(A,B): print(A,B) sys.exit() X=42 Button(None,text='HI',command=(lambda :handler(X,"spam"))).pack() mainloop()方式2:对象引用实现延迟调用
from tkinter import * #对象引用实现延迟调用 def handler(A,B): print(A, B) sys.exit() X=42 def func(): #调用要实现的函数 handler(X,'spam') #command=中间函数 Button(None,text='HI',command=func).pack() mainloop()这个代码是下面两个例子的基础:
# -*-coding:utf-8-*- #-*-md10_用类实现复用GUI部件.py-*- from tkinter import * class Hello(Frame): def __init__(self,parent=None): Frame.__init__(self,parent) self.pack() self.data = 42 self.make_widgets() def make_widgets(self): #self即Hello本身,继承了Frame widget = Button(self,text='Hello frame world!',command=self.message) widget.pack(side=TOP) widget1 = Button(self,text='关闭',command=self.quit) widget1.pack(side=BOTTOM) def message(self): self.data += 1 print('Hello frame world %s!'%self.data) if __name__ == '__main__': Hello().mainloop()下面的 代码引用上一个文件的类,实现模块化。
# -*-coding:utf-8-*- from tkinter import * from md10_用类复用GUI部件 import Hello class HelloContainor(Frame): def __init__(self,parent=None): Frame.__init__(self,parent) self.pack() self.makeWidgets() def makeWidgets(self): #将上一个py文件中Hello类实现的组件一起添加打包到Frame上,实现模块化 Hello(self).pack(side=RIGHT) Button(self,text='Attach',command=self.quit).pack(side=LEFT) if __name__ == '__main__': HelloContainor().mainloop()引用父类的函数实现组件部署,调用的却是子类本身的回调函数:
''' 扩展类部件 ''' from tkinter import * from md10_用类复用GUI部件 import Hello class HelloExtender(Hello): def make_widgets(self): Hello.make_widgets(self) Button(self,text='Extend',command=self.quit).pack(side=RIGHT) def message(self): print('Hello',self.data) if __name__ == '__main__': HelloExtender().mainloop()上面使用类完成组件的一些列过程,但是类本身都是基础了tkinter组件类的,即:类的实例对象就是一个组件,可以直接mainloop运行的;下面代码使用思维:类本身不是组件,没有基础tkinter任何组件类,而在类里面去实现组件的一些列过程。即:类的实例不能直接mainloop运行。
# -*-coding:utf-8-*- from tkinter import * class HelloPackage: def __init__(self,parent=None): self.top = Frame(parent) self.top.pack() self.data = 0 self.make_widgets() def make_widgets(self): Button(self.top,text='Bye',command=self.top.quit).pack(side=LEFT) Button(self.top,text='Hye',command=self.message).pack(side=RIGHT) def message(self): self.data +=1 print('Hello number',self.data) if __name__ == '__main__': # 所有的组件都在Frame上,而HelloPackage并不是组件,只是一个类(用来存储真实组件对象及信息); # 所有的组件依附于self.top,若我们要启动GUI,就需要self.top.mainloop();而不是self.mainloop() HelloPackage().top.mainloop()对上面独立的容器类的引用:
from tkinter import * from md14_独立的容器类 import HelloPackage frm = Frame() frm.pack() Label(frm,text='hello').pack() part = HelloPackage(frm) part.top.pack(side=RIGHT)#注意:这里必须要一个top,因为HelloPackage类只是一个容器类,所有组件依附于self.top frm.mainloop()比较完美的解决方式是:通过定义方法将获取的不明属性引导至内嵌至的Frame;
步骤1:创建一个获取类属性的中间类
#引用上面的py文件 from md14_独立的容器类 import HelloPackage from tkinter import * class HelloPackage(HelloPackage): def __getattr__(self, item): return getattr(self.top,item)#完成并传递到一个实际的组件步骤2:再引用上面的类
from tkinter import * from md15_config import HelloPackage frm = Frame() frm.pack() Label(frm,text='hello').pack() part = HelloPackage(frm) part.pack(side=RIGHT) frm.mainloop()