详细介绍Qt的信号与槽交流机制

描述

引言

前面讲各种事件响应的时候说过一些关于信号与槽的绑定,实现相关的事件响应,但是并没有深入跟详细的介绍,之前的事件信号基本上都是QT的build-in信号,响应的槽函数基本上都是用户自定义的函数,本文将会详细介绍Qt的信号与槽交流机制。

元对象系统

PyQT5中QGUI中当用户改动一个QWidget的状态时,可以通过支持的信号触发相关的槽函数完成动作交互。其它的GUI库多数都是通过Callback(回调)实现消息传递与触发,QT的这种方法在更广泛的层面是它底层的元数据对象系统(Meta-Object System )。元数据对象系统提供了信号与槽机制在不同的对象内容交互数据与信息,元数据对象支持信号与槽机制主要依赖:  

 

- 所有的QWidget对象都是QObject类都是元数据
- C++使用Q_OBJECT宏定义在私有变量中的类才是元数据
- 元数据对象编译器会提供QObject类子类完成必要的代码实现元对象特性
 

 

信号与槽

信号与槽机制中在GUI层面的信号主要是指靠用户触发特定事件产生,所以QWidget对象不同GUI组件预定义了大量的内置信号,开发者在使用这些QWidget组件时只要把这些信号绑定到自定义的槽函数即可实现特定事件的响应触发特定方法。任意一个绑定信号的响应函数都可以被称为槽函数,槽函数跟信号是松散耦合的关系,只有当槽函数被链接到特定信号的时候它才会响应特定事件。一个槽函数可以被链接到多个信号实现响应,同样一个信号可以被不同的槽函数链接。信号与槽是QT编程架构中最重要的组件之一。

信号

PyQT5中的信号分为两种一种是build-in的信号,主要是跟不同QWidget组件产生特定关联,比如valueChanged、toggled、clicked等这些信号;另外一类信号是开发者自定义信号,这些信号可以帮助开发者实现数据交互、特定界面刷新、在不同线程之间传递消息等等。builid-in的信号不需要开发者激发,开发者只要绑定到特定的槽函数即可实现在动作响应时自定激发;自定义信号必须通过显式调用的方式激发:

 

custom_signal.emit(parameters)

 

槽函数

任何一个正常的函数都可以成为槽函数,类的实例方法通过信号链接成为槽函数之后被直接调用而不需要开发者再初始类实例代码。相比直接通过接口回调的方式,信号与槽架构方式带来了很大的灵活性,但是同时也会带来更多的执行调用时间,QT官方文档指出这样方法相比回调响应过程会慢一点。

代码演示部分

代码演示部分只演示自定义信号跟自定义槽函数是如何工作的,build-in信号跟自定义槽函数在之前的文章中实际已经演示了很多次,这里不在重复代码演示。

数据类含有自定义信号

 

 1class MyTextData(QtCore.QObject):
 2    fire_draw_text_signal = QtCore.pyqtSignal(str)
 3
 4    def __init__(self):
 5        super(MyTextData, self).__init__()
 6        print("create my text...")
 7        self.text_content = "OpenCV开发者联盟"
 8
 9    def text_changed(self, text):
10        self.text_content = text
11        self.fire_draw_text_signal.emit(self.text_content)
初始化,绑定自定义信号与自定义槽函数
1# 初始化自定义数据类
2self.my_data = MyTextData()
3self.my_data.fire_draw_text_signal.connect(self.show_text)
4self.my_data.text_changed("自定义信号演示")
自定义槽函数
 1def show_text(self, text):
 2    painter = QtGui.QPainter(self.label.pixmap())
 3    pen = QtGui.QPen(QtCore.Qt.green)
 4    painter.setPen(pen)
 5    font = QtGui.QFont()
 6    font.setBold(True)
 7    font.setPointSizeF(24)
 8    painter.setFont(font)
 9    painter.drawText(QtCore.QPoint(20, 50), "OpenCV演示-" + text)
10    painter.end()
触发与调用
 1def on_update_gray(self):
 2    image = cv.imread("images/test5.png")
 3    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
 4    dst = cv.cvtColor(gray, cv.COLOR_GRAY2RGB)
 5    height, width, channel = dst.shape
 6    bytesPerLine = 3 * width
 7    img = QtGui.QImage(dst.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888)
 8    pixmap = QtGui.QPixmap(img)
 9    pix = pixmap.scaled(QtCore.QSize(620, 500), QtCore.Qt.KeepAspectRatio)
10    self.label.setPixmap(pix)
11    self.my_data.text_changed("图像灰度化")
会自动绘制指定文本到QLabel标签的图像上,代码运行结果如下:

回调函数

 

回调函数

回调函数






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分