QObject为pyqt中所有控件的基类,QObject中的所有方法都可以在其他控件中使用
目录
4.1 释放一个父对象,他的所有子对象也自动会被释放(下面这个例子不能证明此观点)
4.2 当有指针指向时,obj1不会被自动释放,他的子对象即使没有指针也不会被自动释放
5.4 可通过blockSignals(bool)控制槽函数的通断
1 QObject继承结构测试
可以使用方法__subclasses__()查看QObject中的所有子类
使用mor链条查看QObject的父类
- QObject为sip.wrapper的子类 → sip.wrapper为sip.simplewarapper的子类 → sip.simplewrapper为object的子类
- 最终结论为QObject继承python内建库中的object
1.1 小结
- pyqt中所有控件的最终父类皆为QObject
- QObject最终父类为python中的Object
- 可使用mro方法进行验证,此方法在python内置语言中同样存在
2 QObject对象名称和属性的操作
- 实例化后,通过方法setObjectName()设置对象姓名
运行结果
- 通过方法setProperty()设置属性
运行结果
- 通过方法dynamicPropertyNames()获取对象的所有属性
运行结果
2.1 小结
- 可使用setObjectName()定义对象名称
- 可使用setProperty()定义属性名称
- 可使用dynamicPropertyNames()获取对象所有属性
3 QObject对象父子关系操作
通过setParent()可以对QObject设置父子关系,代码中obj2为obj1的父对象
运行结果
- 注:一个对象的父对象只能有一个,如果在代码中对一个对象使用多次setParent(),则该对象的父对象为最后一次使用setParent()的目标
- 当前示例中,obj3为obj2的父对象,obj2为obj1的父对象
可以通过children()获取对象所有直接子对象
- 注:控件(如label,pushbutton的父对象只能为控件,不能为object
findChild()查找指定类型的子对象,方法findChild()只能返回一个子对象
- findchild()第一个参数为要寻找的子对象的类型
运行结果
如果给定类型还无法区分的话,设置子对象的objectname,findChild()第二个参数为objectname
运行结果
如未能找到会返回None
运行结果
findChild()的功能为可找到变量的所有子对象,其第三个参数可以取消这个功能
- 第三个参数有两个值:
- Qt.FindChildrenRecursively 该值为默认选项,此值为递归查找(查找所有子对象)
- Qt.FindDirectChildrenOnly 此值为直接查找(只查找直接子对象)
第三个参数使用案例如下
通过findchildren(),可以查找类的所有子对象(直接与间接)
使用案例如下
- 1.使用findChildren()时一定要加参数,没有参数的话会报typeerror
- 2.findChildren()同样有三个参数,参数顺序与内容与findChild()相同
3.1 小结
- 1.在Pyqt中一个对象的父对象只能有一个,但在python中可以有多个
- 2.可通过setparent()为对象设置父对象
- 3.可通过children()获取对象所有直接子对象
- 4.可通过findChild()查找执行类型的子对象,此方法只能返回一个子对象,findChild()三个参数按顺序如下
- 1.要寻找的子对象的父对象
- 2.要寻找的子对象的对象名称(objectname)
- 3.查找方式
- 1.Qt.FindChildrenRecursively(递归查找)
- 2.Qt.FindDirectChildrenOnly(直接查找)
- 5.可通过findChildren()查找所有子对象,此方法同样有三个参数,三个参数与findChild()相同
- 6.如findChild()与findChildren()未能找到子对象,返回None
4 内存管理机制
4.1 释放一个父对象,他的所有子对象也自动会被释放(下面这个例子不能证明此观点)
- 注:
- 1.当对象没有被指针指向的时候,对象会被自动释放,此例中obj1自动释放
- 2.取消obj2与obj1父子关系后,obj2对象同样显示“obj2对象被释放了”
运行结果
4.2 当有指针指向时,obj1不会被自动释放,他的子对象即使没有指针也不会被自动释放
运行结果
4.3 此次使用手动释放可证明论点1
运行结果
- 注:子控件显示的大小不会超过父控件
4.4 内存管理机制应用场景
例如上面这个界面,点击右上角的“×”,在释放最外窗口的同时,其中的所有的子控件也都会被自动释放,而不用一个一个释放
- 注:如果一个控件,没有任何父控件,此控件就会被当成顶层控件(窗口)
5 信号与槽
在pyqt中,信号为if的条件,槽为执行的内容
注:
- 1.一个信号可以连接多个槽
- 2.一个信号可以连接多个其他信号
- 3.一个槽可以监听多个信号
5.1 destroyed信号
有指针时obj不会被释放,不被释放导致不执行槽函数
关闭窗口后的运行结果
可使用del手动释放,或不给obj指针自动释放
手动释放
自动释放
运行结果相同,均为在未关闭页面时执行槽函数
有些信号可在发射的时候传递参数(下图为pyqt库中的代码),如
比如说我在destroyed中pass的上一行加入print(QObject),则可显示被释放的对象,同理此变量可被其他函数调用
也可在槽函数中接收destroyed的信息
运行结果
此信号可传递被关闭的控件信息
5.2 objectNameChanged信号
运行结果
同样可在槽函数中接收objectNameChanged的信息
运行结果
此信号可传递新的对象名称信息
5.3 可使用disconnect取消连接
如果没有倒数第二行,槽函数会执行两遍
取消连接后只会执行一遍槽函数
- 注:此用法可以用只想执行单次的代码,运行之后取消连接,消除bug
5.4 可通过blockSignals(bool)控制槽函数的通断
其中True为允许阻断,False为拒绝阻断
运行结果
- 注:blockSignals()并非完胜于.disconnect()与.connect()的结合,blockSignals作用为阻断对象的所有信号,当一对象时对多信号时不方便使用
blockSignals(True)会一直阻断信号直到blockSignals(False)
运行结果
可以通过signalsBlocked()信号阻绝情况
运行情况
可通过.receivers查看某对象的某个信号连接了多少个槽
运行结果
结果为该信号连接了一个槽
5.5 windowTitleChanged信号
当更改window题目时此信号触发
- 去掉window.setWindowTitle('hello world')后不触发函数
此信号可以传递设定的窗口标题参数title
如要更改定制标题则
5.6 小结
- 1.object内置两种信号(即在pyqt中所有控件都有两种信号):destroyed(释放),objectNameChanged(改变对象名称)
- 2.使用disconnect可以取消信号与槽的连接
- 3.使用blockSignals(bool)控制信号与槽连接的通断
- True 断
- False 通
- 4.使用signalsBlocked()显示信号的通断
- 返回值为True 断
- 返回值为False 通
- 5.使用receivers查看信号的槽个数
- 6.window内置windowTitleChanged(当窗口名称改变时触发)
6 类型判定
- 学习中可将类型判定性函数类比为内置库中的type()
6.1 isWidgetType()
- 判断变量是否为控件,如果是返回True
isWidgetType()返回布尔量,可以直接与If配合使用
类似于内建库中的:
6.2 inherits()
- 参数为父对象,如果变量继承自指定的父对象则返回True(直接继承与间接继承或本身都为True)
本身:
6.3 使用inherits()控制样式表
7 QObject对象删除
7.1 deleteLater()与del的区别
7.1.1 del
运行结果(没有激活槽)
del为删除obj2栈中的指向,但obj2也被obj1引用,所以不会被释放
7.1.2 deleteLater()
运行结果(槽函数被激活了)
两种删除方式下显示obj1的子对象都为obj2
使用del删除显示obj2为,obj2并没有被删除
使用deletelLater删除,说明第一个循环内没有被删除,在之后才将obj2释放
- 结论:
- del为删除变量与对象的关系,如想删除控件则使用deleteLater
- deleteLater为在执行完消息循环后删除
7.2 删除一个控件的案例
删除前
删除后