继承关系及其作用
在部件类的继承关系树上,QObject与QPaintDevice两个类位于最顶端。其中,QObject的核心功能就是提供了信号和槽机制,最为主要的是使对象间能无缝通信,而且QOject还在Qt中提供了基础的定时器的支持,所有使用了信号和槽或属性的类,都需要包含Q_OBJECT这个宏(在原生C++版的QT中建议都加上,在pyqt中不需要,因所有部件类的顶级父类QWidget继承自QObject);而QPaintDevice则提供了一些绘图功能,其虚函数由QWidget、QImage、QPixmap、QGLPixelBuffer等子类各自实现。
QObject常用功能详解
此处为了调试与运行的方便,使用pyqt来进行具体功能讲解,有QT基础者阅读本文代码应该无大碍。
常用方法介绍
设置父控件对象,其函数原型如下:
# 设置父控件
def setParent(self, QObject): # real signature unknown; restored from __doc__
""" setParent(self, QObject) """
pass
其作用一是为一个Widget控件设置父控件,由于“对象树”这种内存管理机制,父控件对象销毁时,将以其为根节点的树上所有对象内存回收;作用二是,无父对象的控件,将会成为一个顶级窗口,需要调用show方法才能展示出来,有父对象的控件则不需要,示例代测试代码如下:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
btn1 = QPushButton()
# 设置提示文本
btn1.setText("我是按钮一")
btn1.show()
window = QWidget()
btn2 = QPushButton("我是按钮二",window)
window.show()
sys.exit(app.exec_())
本代码运行后,将会出现两个窗口,如下所示:
与销毁相关的函数和信号,函数、信号原型如下:
def deleteLater(self): # real signature unknown; restored from __doc__
""" deleteLater(self) """
pass
def destroyed(self, p_object=None): # real signature unknown; restored from __doc__
""" destroyed(self, object: QObject = None) [signal] """
pass
python语法中有个删除的关键字del,在此处使用del会出现问题,并不会将del对象的子控件也删除,需要使用deleteLater,测试代码与注释如下:
def test3(self):
"""
对象被删除时
会解除与父对象的关系
删除要使用deletelater
"""
obj1 = QObject()
obj2 = QObject()
obj3 = QObject()
obj3.setParent(obj2)
obj2.setParent(obj1)
obj1.setParent(self)
# 在对象销毁时会发射destroyed信号
obj1.destroyed.connect(lambda :print("obj1被释放"))
obj2.destroyed.connect(lambda: print("obj2被释放"))
obj3.destroyed.connect(lambda: print("obj3被释放"))
# 这个删除 可以将对象及其子类也删除
# obj2.deleteLater()
# 直接删除 并不会将子控件删除
# 会将obj2删除,但不会发送destroyed信号
del obj2
定时器相关,函数原型如下:
# 计时器每隔多少毫秒触发timerEvent函数
def startTimer(self, p_int, timerType=None): # real signature unknown; restored from __doc__
""" startTimer(self, int, timerType: Qt.TimerType = Qt.CoarseTimer) -> int """
return 0
# 一个对象可开启多个定时器 多个定时器通过ID来区别 也通过ID来关闭
def killTimer(self, p_int): # real signature unknown; restored from __doc__
""" killTimer(self, int) """
pass
# 需要override才能有具体作用
def timerEvent(self, QTimerEvent): # real signature unknown; restored from __doc__
""" timerEvent(self, QTimerEvent) """
pass
窗口中若想设置倒计时,则优先考虑到定时器,下面是简单封装的一个有倒计时效果的label与注释:
class MyLabel(QLabel):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# 此处可以设定 或 改写成随输即用的形式
self.setText("10")
self.setStyleSheet("font-size:22px;")
# 开启定时器 每1s触发一次event
self.timeID = self.startTimer(1000)
# 从10开始,减少到0为止
def timerEvent(self, evt) -> None:
cur = int(self.text())
cur -=1
if cur > 0:
self.setText(str(cur))
else:
self.setText(str(0))
# 关闭定时器
self.killTimer(self.timeID)
信号相关的函数,函数原型与作用如下:
# 获取阻塞状态
def signalsBlocked(self): # real signature unknown; restored from __doc__
""" signalsBlocked(self) -> bool """
return False
# 断开连接
def disconnect(self, QMetaObject_Connection=None): # real signature unknown; restored from __doc__ with multiple overloads
"""
disconnect(QMetaObject.Connection) -> bool
disconnect(self)
"""
return False
# 这两个函数用来追踪连接
def connectNotify(self, QMetaMethod): # real signature unknown; restored from __doc__
""" connectNotify(self, QMetaMethod) """
pass
def disconnectNotify(self, QMetaMethod): # real signature unknown; restored from __doc__
""" disconnectNotify(self, QMetaMethod) """
pass
# 设置暂时阻塞信号以避免无限通知循环
def blockSignals(self, bool): # real signature unknown; restored from __doc__
""" blockSignals(self, bool) -> bool """
return False
值得注意的是,原生C++QT的connect、disconnect使用方法与上述的不相同,pyqt的connect使用为:对象.信号.connect(槽方法),C++的为:connect(sender, SIGNAL(signal()), receiver, SLOT(slot()))或者connect(sender,&sender::signal,receiver,&receiver::slot),简要测试代码与注释如下:
def test_slots1(self):
obj = QObject()
def slots1():
print("有对象被释放")
def slots2(name):
print("对象名称发生了改变",name)
# 信号连接槽函数 对象.信号.connect(槽方法)
obj.destroyed.connect(slots1)
# 有参数的信号发射时 会将参数传出来
obj.objectNameChanged.connect(slots2)
# 信号与槽函数断开连接
obj.objectNameChanged.disconnect()
# 暂时阻断连接
print(obj.signalsBlocked(),"1")
# 设置阻断
obj.blockSignals(True)
print(obj.signalsBlocked(),"2")
obj.blockSignals(False)
print(obj.signalsBlocked(),"3")
# 由于本信号与槽函数已断开连接 slots2将不会被触发
obj.setObjectName("哈哈哈")
与判定相关的函数,原型与作用如下:
# 判断某个对象是否是 以类名为p_str的类为根节点的继承树上一个类实例
def inherits(self, p_str): # real signature unknown; restored from __doc__
""" inherits(self, str) -> bool """
return False
# 某个信号是否连接
def isSignalConnected(self, QMetaMethod): # real signature unknown; restored from __doc__
""" isSignalConnected(self, QMetaMethod) -> bool """
return False
# 是否是widget类型
def isWidgetType(self): # real signature unknown; restored from __doc__
""" isWidgetType(self) -> bool """
return False
# 是否是window类型
def isWindowType(self): # real signature unknown; restored from __doc__
""" isWindowType(self) -> bool """
return False
简易测试代码与注释如下:
def test1(self):
btn = QPushButton(self)
btn.setText("putton1")
def slots1():
QMessageBox.information(None,"tip","clicked button")
btn.clicked.connect(slots1)
# 类型判定
# True
print(btn.isWidgetType())
# False
print(btn.isWindowType())
# 继承判定 ClassName
# True
print(btn.inherits("QWidget"))
其它方法,如setProperty、setObjectName等,作用在于设置具体对象的动态属性,一般与QSS进行搭配使用来设置控件样式,由于篇幅原因,感兴趣的读者可自己进行测试,如觉得本文对你有帮助,请点赞关注一下。