详细介绍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 = text11        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标签的图像上,代码运行结果如下:


电子元器件购买流程步骤
西门子plc关于流量累计功能相关问题分享
英飞凌最新推“带线圈的模块”芯片封装技术
中国扫地机器人行业快速发展,渗透率仍有较大提升机空间
基于Shannon Open-Channel的高性能KV存储应用实践
详细介绍Qt的信号与槽交流机制
福特全新Ranger最新消息:超丰富配置搭3.2动力,或将于明年正式上市!
NVIDIA AI平台在MLPerf基准测试实现飞跃
汽车后视镜控制设计的解决方案
创建并运行您的第一个网页UI测试用例
超级电容为何迟迟没大量投入市场使用?
从写诗敲代码到临床问诊,AI大模型会是智慧医疗的强力催化剂吗?
中文大模型基准测评2023年度报告
BOE(京东方)推出了可应用于AMOLED显示领域的屏下指纹识别解决方案
封装LED发光二极管正负极判断
浅谈三维大数据可视化平台
机器视觉类公司“瞄上”半导体封装等环节
电流互感器和电压互感器的配置原则及类型选择
数码管显示电压电路图大全(六款数码管显示电压电路原理图详解)
为什么退耦电容通常选0.1uF?