QObject
- 在Qt中QObject是所有类的基类,换而言之是在Qt中所有的类均继承自QObject,这使得QObject中的所有方法在其它类中使用。所以学习QObject中的方法有其特殊的意义。
继承结构测试的方法
from PyQt5.QtCore import QObject
obj = QObject()
mros = QObject.mro()
for mro in mros:
print(mro)
对象名称、属性相关操作
from PyQt5.QtCore import QObject
obj = QObject()
obj.setObjectName("new_object_name")
obj.objectName()
obj.setProperty("property_name", value)
obj.property("property")
obj.dynamicPropertyNames()
obj.setObjectName('new_object_name')
obj.objectName()
obj.setProperty("property_name",value)
obj.property("property_name")
- 获取一个对象中通过setProperty()设置的所有属性名称
obj.dynamicPropertyNames()
- 应用场景用于qss的ID选择器和属性选择器,同时可以应用于装饰墙的信号与槽;
父子对象操作
obj1 = QObject()
obj2 = QObject()
print(obj1)
obj2.setParent(obj1)
obj2.parent()
print(obj2)
obj1.children()
obj.findChild(参数1, 参数2, 参数3)
objfindChildren(参数1, 参数2, 参数3)
- 应用场景:
- 涉及到Qt对象的内存管理机制;
- 如果一个控件没有父控件,则会被当成顶层控件来使用;
- 如果想要一个控件被包含在控件内部,就需要设置父子关系;
信号处理
- 需要了解QObject的信号处理,首先需要了解的是什么是信号与槽机制,信号(signal)和槽(slot)是Qt中的核心机制,主要作用在于对象之间的通信。
- 信号指的是,当一个控件的状态发生改变时,向外发射信息;
- 槽指的是,一个执行某些操作的函数/方法。所有继承自QWidget的控件都支持“信号与槽”的机制。
- 一个信号可以连接多个槽函数;
- 一个信号也可以连接另一个信号;
- 信号的参数可以是任何python类型;
- 一个槽可以监听多个信号。
widget.信号.connect(槽函数)
对象被销毁时发射的信号
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QApplication, QWidget
import sys
class Test_slot(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
obj = QObject()
obj.destroyed.connect(self.slot_fun)
self.show()
def slot_fun(self):
print("aaaa")
if __name__ == "__main__":
app = QApplication(sys.argv)
test = Test_slot()
sys.exit(app.exec_())
对象名称发生改变时发射此信号
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QApplication, QWidget
import sys
class Test_slot(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
obj = QObject()
obj.setObjectName("init_object_name")
obj.objectNameChanged.connect(self.slot_fun)
obj.setObjectName("new_object_name")
self.show()
def slot_fun(self, return_value):
print("对象名称改变了", return_value)
if __name__ == "__main__":
app = QApplication(sys.argv)
test = Test_slot()
sys.exit(app.exec_())
信号的其他操作
obj = QObject()
obj.信号.connect(槽函数)
- 取消对象信号连接,切断信号与某个槽函数的连接,切断之后可以再次执行连接函数进行重新连接
obj.信号.disconnect()
obj.blockSignals(True/False)
obj.signalsBlock()
- 返回连接信号接收器的数量(一个信号可以连接多个信号)
obj.receivers(obj.信号)
类型判定
- 类型的判定是一个比较简单的概念,有两个功能:
- 一个是用于判断某一个对象是否是一个控件;
- 另一个是判断其是否继承自某一个父类。
判断某一对象是否为控件类别
obj = QObject()
win = QWidget()
btn = QPushButton()
lab = QLable()
isWidgetType(obj)
isWidgetType(win)
isWidgetType(btn)
isWidgetType(lab)
判断一个对象是否继承(直接继承或间接继承)于某个类
obj.inherits(父类)
对象删除
- 在Qt中提供了一个对象删除方法deleteLater()。在删除一个对象时,也会解除它与父对象之间的关系。
- 从字面上理解可以知道,deleteLater()并没有将对象立即销毁,而是向著消息循环发送一个event,下一次著消息循环到这个event之后才会销毁对象;这样的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时。
事件处理
- 信号与槽可以说是对事件机制的高级封装,事件机制是更为底层的概念;用户的操作都会产生一个事件消息(如鼠标点击事件、键盘敲击事件),这些操作事件消息将发送给操作系统,操作系统会将消息分发到对应的应用程序“消息队列”中;应用程序中的消息循环,会不停的监听队列中是否有时间消息。

- 当检测到队列中有时间消息时,就会将事件接收者(receiver)和事件对象(evt)传递给QApplication对象的notify(receriver,evt),再由该方法进行分发,即分发给receiver对象的event(evt)方法,此方法会根据evt的事件类型分发给receiver具体的事件函数;如mousePressEvent(evt)、mousePeleaseEent(evt)等等;
import sys
from PyQt5.Qt import *
class App(QApplication):
def notify(self, receiver, evt):
if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
print(receiver, evt)
return super().notify(receiver, evt)
class Btn(QPushButton):
def event(self, evt):
print(evt)
return super().event(evt)
app = App(sys.argv)
window = QWidget()
btn = Btn(window)
btn.setText('button')
btn.move(100, 100)
def slot_fun():
print('按钮被点击了')
btn.pressed.connect(slot_fun)
window.show()
sys.exit(app.exec_())
定时器
- 创建一个定时器,可以在规定的时间向外发送一个timerEvent()信号,我们可以改写类里面的timerEvent()方法,从而实现按规定时间执行某一操作;
- 使用的API有:
startTimer(ms, Qt.TimerType)
timerEvent()
killTimer(timer_id)
代码示例
from PyQt5.Qt import *
import sys
class MyObject(QObject):
def timerEvent(self, evt):
print(evt)
app = QApplication(sys.argv)
window = QWidget()
obj = MyObject()
timer_id = obj.startTimer(1000)
window.setWindowTitle('')
window.resize(500, 500)
window.show()
sys.exit(app.exec_())