Qt信号和槽及自定义类型注册

一、环境

  • 系统:Window10 64企业版
  • Qt:qt5.12.12
  • VS:vs2017企业版
  • addin:2.8.1.6

二、信号和槽

2.1信号

  • Qt通过类中声明的信号和槽函数实现类(同一个类或不同类)的对象之间信息流的联动。
  • 信号:
    • 自定义声明关键字:signal;
    • 信号类似void返回值函数的声明方法;
    • 信号没有实现只有声明;
    • 信号的触发方式在指定函数位置emit signalName();
    • 信号可以不加参数,也可以添加参数。当添加参数时参数分为系统默认支持的数据类型和自定义数据类型的两种,信号需要传递自定义参数需要手动注册这种数据类型,注册方法:类的声明部分需要添加:
   使用方法(声明和注册自定义数据类型)
   
   1)引入头文件:#include<QMetaType>
  
   2)添加声明(一般在.h文件):利用宏 Q_DECLARE_METATYPE
   
   //这个函数一定要用在调用或者绑定信号槽前
   3)注册(一般在.cpp文件构造函数中):利用方法 qRegisterMetaType

本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓  

2.2槽函数

  • 槽函数:
    • 当信号被触发响应信号的响应处理;
    • 返回值为void类型,参数和信号一致,可以接收信号传递过来的值(自定义参数需要注册);
    • 可以跨线程;
    • 信号和槽的关联方式一般分为两种:系统根据规则自动关联信号和槽;手动声明信号和槽函数关联关系。
    • 信号和槽根据名称自动关联的原因是下面这个语句:
   //在ui文件生成的.h文件会发现下面这个语句
   
   QMetaObject::connectSlotsByName(xxxClass);

2.3关联信号和槽的方法

信号和槽的关联方式:

  • QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
  • 参数说明:第一个参数是信号发送对象的地址指针(注意是对象不是类),第二个参数发送的信号地址,第三个接受者对象地址,第四个接收者处理方法,第五个参数关联类型。

具体使用过程有两种方式:

  1. Qt4.0中常用,支持信号和槽函数重载,例如:connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(pushButon1_clicked()));
  2. Qt5以后使用的新的绑定方法,不支持信号和槽的重载。但是这种新的方法去掉了使用的宏,改为信号和槽的类,例如:
  3. connect(ui->pushButton_2,&QPushButton::clicked,this,&::MainWindow::pushButon2_clicked);
  4. 类似lamda表达式,槽函数直接实现:connect(ui->pushButton_4, QOverload<bool>::of(&QPushButton::clicked),[=](bool check){ ui->textBrowser->setText("按钮4信号绑定成功");});

connect第五个参数:

  • connect具体使用过程经常只用四个参数,第五个参数用默认值。

第五个参数使用过程几个值及相关意义:

  1. Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
  2. Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃
  3. Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。
  4. Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
  5. Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

关于线程:

  1. QThread 是用来管理线程的,它所依附的线程和它管理的线程并不是同一个线程;
  2. QThread 所依附的线程,就是执行 QThread t(0) 或 QThread * t=new QThread(0) 的线程。也可以看作主线程
  3. QThread 管理的线程,就是 run 启动的线程。也就是子线程,只有run函数中创建的对象,才属于子线程(注意qudpsocket跨线程报错),继承自QThread的线程类的成员函数和成员变量都不在子线程;
  4. 因为QThread的对象依附在主线程中,所以他的slot函数会在主线程中执行,而不是子线程。除非:QThread 对象依附到子线程中(通过movetoThread)slot 和信号是直接连接,且信号在次线程中发射
    但上两种解决方法都不好,因为QThread不是这么用的(Bradley T. Hughes)

2.4取消信号和槽的关联

使用方法和connect类似,关键字用disconnect即可。此过程不需要第五个参数。

取消方式:

bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)

三、自定义类型注册

注册方法及步骤:

  1. 自定义类型(结构体/类),声明文件包含QMetaType:#include <QMetaType>;
  2. 自定义类型结尾通过宏Q_DECLARE_METATYPE,注册:Q_DECLARE_METATYPE(MyClassType);
  3. 建立信号槽关联connect之前用qRegisterMetaType注册(这个类文件也需要包含头文件QMetaType:#include <QMetaType>)

注意:Q_DECLARE_METATYPE、qRegisterMetaType注册过程对象、引用、指针是不一样的。

示例:

   //自定义类型文件
   #include <QMetaType>
   
   //
   Q_DECLARE_METATYPE(Custom)
   
   
   //关联信号槽的类文件
   qRegisterMetaType<Custom>("Custom&");

文章转自博客园(mehome ):Qt信号和槽及自定义类型注册 - mehome - 博客园

本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓ 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值