类型判定
-
API
obj.isWidgetType() # 判断对象是否是控件类型(是否继承自QWidget类) obj.inherits('父类') # 一个对象是否继承(直接或者间接)自某个类
-
示例
from PyQt5.Qt import import sys class Windows(QWidget): def __init__(self): super().__init__() self.setWindowTitle('QObject_类型判断') self.resize(980, 500) self.widget_list() def widget_list(self): self.add_widget() def add_widget(self): obj = QObject() win = QWidget() btn = QPushButton() lab = QLabel() # 给每个对象设置对象名称 obj.setObjectName('obj') win.setObjectName('win') btn.setObjectName('btn') lab.setObjectName('lab') # 将对象添加到列表,方便循环判断 objs = [obj, win, btn, lab] for o in objs: print(f'{o.objectName()} is WidgetType:', o.isWidgetType()) print(f'{o.objectName()} inherit QObject:', obj.inherits('QObject')) print(f'{o.objectName()} inherit QWidget:', obj.inherits('QWidget')) print(f'{o.objectName()} inherit QPushButton:', obj.inherits('QPushButton')) print() if __name__ == '__main__': app = QApplication(sys.argv) w = Windows() w.show() sys.exit(app.exec_())
-
输出结果
-
应用场景
- 过滤筛选控件
-
案例
- 创建一个窗口, 包含多个QLabel或其他控件
- 将包含在窗口内所有的QLabel控件, 设置背景色cyan
from PyQt5.Qt import * import sys class Windows(QWidget): def __init__(self): super().__init__() self.setWindowTitle('QObject_类型判定案例') self.resize(980, 500) self.widget_list() def widget_list(self): self.add_widget() def add_widget(self): lab1 = QLabel(self) lab1.setText('我是一个标签1') lab1.move(100, 100) lab2 = QLabel(self) lab2.setText('我是一个标签2') lab2.move(100, 150) lab3 = QLabel(self) lab3.setText('我是一个标签3') lab3.move(100, 200) btn1 = QPushButton(self) btn1.setText('我是一个按钮1') btn1.move(100, 250) btn2 = QPushButton(self) btn2.setText('我是一个按钮2') btn2.move(100, 300) # 方法一 # for o in self.findChildren(QLabel): # o.setStyleSheet('background-color:cyan;') # 方法二 for o in self.children(): if o.inherits('QLabel'): o.setStyleSheet('background-color:cyan;') if __name__ == '__main__': app = QApplication(sys.argv) w = Windows() w.show() sys.exit(app.exec_())
-
输出结果
对象删除
- API
del语句 # 删除变量到对象的引用和变量名称本身 # 注意del语句作用在变量上,而不是数据对象上 obj.deleteLater() # 延迟删除对象 # deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象
- 删除一个对象时, 也会解除它与父对象之间的关系
- 这样做的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时
- 示例
from PyQt5.Qt import import sys class Windows(QWidget): def __init__(self): super().__init__() self.setWindowTitle('') self.resize(980, 500) self.widget_list() def widget_list(self): self.add_widget() def add_widget(self): obj1 = QObject() obj2 = QObject() obj3 = QObject() obj4 = QObject() self.obj1 = obj1 obj2.setParent(obj1) # 设置obj1为obj2的父对象,obj1销毁,obj2将自动销毁 obj3.setParent(obj2) # 设置obj2为obj3的父对象,obj2销毁,obj3将自动销毁 obj4.setParent(obj3) # 设置obj3为obj4的父对象,obj3销毁,obj4将自动销毁 print(obj1) print(obj2) print(obj3) print(obj4) obj1.destroyed.connect(lambda :print('obj1被释放了')) obj2.destroyed.connect(lambda :print('obj2被释放了')) obj3.destroyed.connect(lambda :print('obj3被释放了')) obj4.destroyed.connect(lambda :print('obj4被释放了')) del obj2 # 这里只是删除了栈中的变量到对象的引用和变量名本身。并没有删除堆中的对象 # print(obj2) # 这里不能再使用obj2这个变量,因为del语句删除变量到对象的引用和变量名称本身 obj3.deleteLater() # 延迟删除堆中的对象 print('del obj2之后') if __name__ == '__main__': app = QApplication(sys.argv) w = Windows() w.show() sys.exit(app.exec_())
- 输出(在窗体关闭之前)
\<PyQt5.QtCore.QObject object at 0x00000298ECB9A670> \<PyQt5.QtCore.QObject object at 0x00000298ECB9A700> \<PyQt5.QtCore.QObject object at 0x00000298ECB9A790> \<PyQt5.QtCore.QObject object at 0x00000298ECB9A820> del obj2之后 obj3被释放了 obj4被释放了
- 从结果可以看到
- del obj2执行之后,并没有被释放出来。因为del语句仅仅是删除变量到对象的引用和变量名称本身,并没有删除对象本身
- obj3.deleteLater()之后,obj3和obj4立马被释放了。是因为deleteLater将obj3这个对象给删除了,obj3又是obj4的父对象,父对象被销毁时子对象跟着被销毁,所有obj4也被释放
- 关于延迟删除示例
from PyQt5.Qt import import sys class Windows(QWidget): def __init__(self): super().__init__() self.setWindowTitle('') self.resize(980, 500) self.widget_list() def widget_list(self): self.add_widget() def add_widget(self): obj1 = QObject() obj2 = QObject() obj3 = QObject() obj4 = QObject() self.obj1 = obj1 obj2.setParent(obj1) # 设置obj1为obj2的父对象,obj1销毁,obj2将自动销毁 obj3.setParent(obj2) # 设置obj2为obj3的父对象,obj2销毁,obj3将自动销毁 obj4.setParent(obj3) # 设置obj3为obj4的父对象,obj3销毁,obj4将自动销毁 print(obj1) print(obj2) print(obj3) print(obj4) obj1.destroyed.connect(lambda :print('obj1被释放了')) obj2.destroyed.connect(lambda :print('obj2被释放了')) obj3.destroyed.connect(lambda :print('obj3被释放了')) obj4.destroyed.connect(lambda :print('obj4被释放了')) del obj2 obj3.deleteLater() print('del obj2之后') print('obj3.deleteLater之后',obj3) if __name__ == '__main__': app = QApplication(sys.argv) w = Windows() w.show() sys.exit(app.exec_())
- 输出结果(窗体关闭之前)
\<PyQt5.QtCore.QObject object at 0x000002635E22A670> \<PyQt5.QtCore.QObject object at 0x000002635E22A700> \<PyQt5.QtCore.QObject object at 0x000002635E22A790> \<PyQt5.QtCore.QObject object at 0x000002635E22A820> del obj2之后 obj3.deleteLater之后 \<PyQt5.QtCore.QObject object at 0x000002635E22A790> obj3被释放了 obj4被释放了
- 结果可以看到,obj3.deleteLater()之后,obj3任然能够被打印出来。是因为deleteLater是延迟删除
- deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象
- 实例说明
from PyQt5.Qt import import sys class Windows(QWidget): def __init__(self): super().__init__() self.setWindowTitle('deleteLater') self.resize(980, 500) self.widget_list() def widget_list(self): self.add_widget() def add_widget(self): bnt1 = QPushButton(self) bnt1.setText('按钮1') bnt1.move(100,100) bnt2 = QPushButton(self) bnt2.setText('按钮2') bnt2.move(200, 100) bnt3 = QPushButton(self) bnt3.setText('按钮3') bnt3.move(300, 100) qw = QWidget(self) bnt4 = QPushButton() bnt4.setParent(qw) bnt4.setText('按钮4') bnt4.move(400, 100) del bnt2 # del 仅仅是删除变量到对象的引用和变量名称本身,并没有删除对象本身 bnt3.deleteLater() # deleteLater() 直接删除对象 qw.deleteLater() # deleteLater() 直接删除父对象之后,子对象自动删除 if __name__ == '__main__': app = QApplication(sys.argv) w = Windows() w.show() sys.exit(app.exec_())
- 展示效果
- del语句仅仅是删除变量到对象的引用和变量本身,并不删除对象
- deleteLater()是延迟删除对象本身