QT入门基础(二)

简介: QT入门基础(二)

四.信号和槽机制


  • 概念:
  1. 信号:各种事件,当某个事件发生后,如某个按钮被点击了一下,它就会发出一个被点击的信号(signal)
  2. 槽: 响应信号的动作,某个对象接收到这个信号之后,就会做一些相关的处理动作(称为槽slot)
  3. 链接:Qt对象不会无故收到某个信号,要想让一个对象收到另一个对象发出的信号,这时候需要建立连接(connect),即建立信号和槽的关系


1.系统信号和槽

  • 示例:建立点击按钮和窗口关闭的联系
QPushButton *quitBtn = new QPushButton("按钮1",this);
connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);


  • 效果:


connect函数是建立信号发送者、信号、信号接收者、槽四者关系的函数:connect(sender, signal, receiver, slot);


  • 参数解释:
  1. sender:信号发送者
  2. signal:信号
  3. receiver:信号接收者
  4. slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

注意:connect的四个参数都是指针,信号和槽是函数指针


  • 系统自带的信号和槽的查找:

55764990432bdbd9d25d2bea62e19b1c.png

  1. 在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入QPushButton
  2. 首先我们可以在Contents中寻找关键字 signals,但是我们发现并没有找到,这时候我们应该想到也许这个信号的被父类继承下来的
  3. 因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个

7c80ffa84b9907bd3d40d086ad9fd232.png

这里的clicked就是我们要找到,槽函数的寻找方式和信号一样,只不过他的关键字是slot


2.自定义信号和槽

Qt框架默认提供的标准信号和槽不足以完成我们日常应用开发的需求,但是Qt信号和槽机制提供了允许我们自己设计自己的信号和槽


  • 自定义信号:
  1. 声明在类的signals域下
  2. 没有返回值,void类型的函数
  3. 只有函数声明,没有定义
  4. 可以有参数,可以重载
  5. 通过emit关键字来触发信号,形式:emit object->sig(参数);


  • 自定义槽函数:
  1. qt4 必须声明在 private/public/protected slots域下面,qt5之后可以声明public下,同时还可以是静态的成员函数,全局函数,lambda表达式
  2. 没有返回值,void类型的函数
  3. 不仅有声明,还得要有实现
  4. 可以有参数,可以重载


  • 使用自定义信号和槽示例:

定义场景:下课了,老师跟同学说肚子饿了(信号),学生请老师吃饭(槽)

  • 老师类中声明信号:
signals:
void hungry();


  • 学生类中声明槽:
public slots:
void treat();


  • 学生类实现槽函数:
void Student::treat()
{
    qDebug() << "Student treat teacher";
}


  • 信号和槽链接:使用connect
teacher = new Teacher(this);
student = new Student(this); connect(teacher,&Teacher::hungury,student,&Student::treat);


  • 信号触发:在窗口中声明一个公共方法下课,这个方法的调用会触发老师饿了这个信号,而响应槽函数学生请客
void MyWidget::ClassIsOver()
{
  //发送信号
  emit teacher->hungry();
}


  • 带参数的信号和槽:
void hungry(QString name); //自定义信号
void treat(QString name );  //自定义槽


对于有两个重名的自定义信号和自定义的槽,直接连接会报错,所以需要利用函数指针来指向函数地址, 然后再做连接

//函数重载 函数指定具有二义性需要进行指定
//1.函数指针赋值
void(Teacher::*tqs)(QString)=&Teacher::hungry;//自动赋值对应类型的函数地址
void(Student::*sqs)(QString)=&Student::treat;
connect(pTeacher,tqs,pStudent,sqs);
//2.使用static_cast转换
connect(pTeacher,
            static_cast<void(Teacher::*)()>(&Teacher::hungry),
            pStudent,
            static_cast<void(Student::*)()>(&Student::treat));
//3.qt4之前使用宏转换
connect(pTeacher,SIGNAL(hungry()),pStudent,SLOT(treat()));
connect(pTeacher,SIGNAL(hungry(QString)),pStudent,SLOT(treat(QString)));


  • 效果:

e1518dda9516f48167e44c21c9dffd5d.png

注:对于使用SIGNAL()和SLOT()宏指定函数,虽然使用简单,但是宏只是做字符串替换,编译时不会检查,所以运行时可能报错


3.信号和槽的拓展

  1. 一个信号可以和多个槽相连

如果是这种情况,这些槽会一个接一个的被调用,但是槽函数调用顺序是不确定的


  1. 多个信号可以连接到一个槽

只要任意一个信号发出,这个槽就会被调用


  1. 一个信号可以连接到另外的一个信号

当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。这里还是使用connect函数,只是信号的接收者和槽函数换成另一个信号的发送者和信号函数


  1. 信号和槽可以断开连接

使用disconnect函数,当初建立连接时connect参数怎么填的,disconnect里边4个参数也就怎么填。当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。


  1. 信号和槽函数参数类型和个数必须同时满足两个条件

信号函数的参数个数必须大于等于槽函数的参数个数

信号函数的参数类型和槽函数的参数类型必须一一对应


4.槽函数使用Lambda表达式

  • 以QPushButton点击事件为例:
connect(btn,&QPushButton::clicked,[=](){
    qDebug()<<"Clicked";
});


  • 效果:

ae34a417a25661adb7a2ef644b60e870.png

  • 说明:
  1. 使用Lambda表达式作为槽的时候不需要填入信号的接收者
  2. 当点击按钮的时候,clicked信号被触发,lambda表达式也会直接运行
  3. 当然lambda表达式还可以指定函数参数,这样也就能够接收到信号函数传递过来的参数了
  4. 由于lambda表达式比我们自己自定义槽函数要方便而且灵活得多,所以在实现槽函数的时候优先考虑使用Lambda表达式
  5. 一般使用习惯也是lambda表达式外部函数的局部变量全部通过值传递捕获进来,也就是:[ = ] ( ) { }的形式


表达式也会直接运行

3. 当然lambda表达式还可以指定函数参数,这样也就能够接收到信号函数传递过来的参数了

4. 由于lambda表达式比我们自己自定义槽函数要方便而且灵活得多,所以在实现槽函数的时候优先考虑使用Lambda表达式

5. 一般使用习惯也是lambda表达式外部函数的局部变量全部通过值传递捕获进来,也就是:[ = ] ( ) { }的形式

相关文章
|
6月前
|
Web App开发 编解码 安全
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
617 4
|
6月前
|
数据挖掘 C++
QT基础入门——项目案例(七)
QT基础入门——项目案例(七)
309 0
QT基础入门——项目案例(七)
|
6月前
|
API
QT基础入门——Qt事件(五)
QT基础入门——Qt事件(五)
365 0
QT基础入门——Qt事件(五)
|
6月前
|
Unix Java Linux
QT基础入门——认识与创建QT(一)
QT基础入门——认识与创建QT(一)
115 0
QT基础入门——认识与创建QT(一)
|
18天前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
88 13
|
25天前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
|
25天前
|
数据可视化 编译器 API
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
|
5月前
|
XML 开发框架 JSON
【Qt】Qt入门
【Qt】Qt入门
|
22天前
|
编译器 API C语言
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
|
5月前
|
计算机视觉
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
76 0
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建