1 添加用户回调函数
1.1 三种回调处理器
1.1.2 lambda 回调处理器
#lambda 基础说明 --> lambda argument:expression
te = lambda c:print(c) # lambda 返回的是一个可运行的函数对象
# 等价于
def te(c):
print(c)
# 处理器,上述例子中,print(c)这个函数被称为处理器
对于GUI的效果:处理器的回调被延迟,可以添加需要的参数。
1.1.2 Bound方法的回调处理器(绑定方法self)
在类中绑定方法。如下所示
class HelloClass:
def __init__(self):
widget = Button(None, test = 'Hello event world', command = self.quit)
widget.pack()
def quit(self):
print('Hello class method world')
sys.exit()
# 实际上传送的参数时 self 和 quit, 如果
这里要特别说明一点,传入一个未绑定的方法在GUI中是不起作用的。
1.1.3 可调用类对象的回调处理器
在可调用类的绑定方法,主要是通过 call 方法来实现拦截运行。例子如下:
import sys
from tkinter import *
class HelloCallable:
def __init__(self):
self.msg = 'Hello __call__ world'
def __call__(self):
print(self.msg)
sys.exit()
经过试验,单独的调用HelloCallable,函数 call 里面的函数不会运行。
扩展1:试验,该种方法,在pyqt是是否可以使用;结论:可用,示例如下:
from PyQt5.QtWidgets import QPushButton,QApplication,QWidget
import sys
class test_call:
def __init__(self):
self.msg = 'test'
def __call__(self):
print(self.msg)
app=QApplication(sys.argv)
w = QWidget()
b = QPushButton(w, text = 'test')
b.clicked.connect(test_call())
w.show()
sys.exit(app.exec_())
扩展2:__call__的本质,实际上是可对对象进行调用,通过"()"符号
2 用类实现组件的自定义设置
1.通过继承的方式,实现自己的定制组件,子类继承超类。
from tkinter import *
class HelloButton(Button):
def __init__(self, parent = None, **config):
Button.__init__(self, parent, **config)
self.pack()
self.config(command=self.callback)
def callback(self):
print("Goodbye world...")
self.quit()
2.用类复用GUI部件 | 添加类部件 | 扩展类部件
大型GUI界面通常作为Frame的子类,用回调处理器作为方法。这种结构,提供了存储事件间信息的天然位置:用实例属性来记录状态。
Frame的子类都是组件,可以通过指定真实的父组件,实现整个组件包依赖于其他某个东西!(这个很重要)
from tkinter import *
# 这是一个依托于Frame实现的一个按钮
class Hello(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
self.data = 1
self.make_widgets()
def make_widgets(self):
widget = Button(self, text='Hello frame world!', command = self.message)
widget.pack(side = LEFT)
def message(self):
self.data += 1
print('Hello frame world %s!' % self.data)
# 把上面的按钮放到另外一个框架中
parent = Frame(None)
parent.pack()
Hello(parent).pack(side=RIGHT) # 把 Hello 作为 parent 的子组件,打包在右侧
Button(parent, text='Attach', command=exit).pack(side=LEFT) # 在左边增加一个按钮
parent.mainloop()
扩展类部件,主要是通过继承并重写类的方法。
3.独立的容器类
通过创建独立容器,来获取前面所提到的所有基于类部件的好处。
优点:可以避免代码命名冲突
类可以通过定义方法,将获取的不明属性引导至内嵌的Frame
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(RIGHT)
def message(self):
self.data += 1
print('Hello number', self.data)
# 通过 __getattr__ 将获取的不明属性 引导至 内嵌的Frame
class HellPackage2(HelloPackage):
def __getattr__(self, name):
return getattr(self.top, name)
# 运行, mainloop()需要对一个组件,这里需要方为到top才是一个Frame
if __name__ == '__main__':HelloPackage().top.mainloop()
3 额外话题 getattr_
这部分问题,可能讨论的不全面,仅为个人的认知。例子说明。
# 属性访问
class test:
def __init__(self):
self.a = 1
self.b = 1
def callback(self, name):
print('get name:{}'.format(name))
def __getattr__(self, name):
print('input name:{}'.format(name)) # 打印传入的变量
return self.callback
# 组合类————组合优于继承,引用于 https://www.cnblogs.com/xybaby/p/6280313.html
class adaptee(object):
def foo(self):
print 'foo in adaptee'
def bar(self):
print 'bar in adaptee'
class adapter(object):
def __init__(self):
self.adaptee = adaptee()
def foo(self):
print 'foo in adapter'
self.adaptee.foo()
def __getattr__(self, name):
return getattr(self.adaptee, name)
if __name__ == '__main__':
a = adapter()
a.foo()
a.bar()
# 在类adapter中就能访问adaptee的属性方法 通过 “.”的形式