文章目录

  • 一、什么是信号槽?
  • 二、信号槽的使用方式
  • 三、自定义信号和槽
  • 四、完整例程

一、什么是信号槽?

信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

二、信号槽的使用方式

connect()函数最常用的一般形式:

connect(sender, signal, receiver, slot);

参数解释:
sender:发出信号的对象
signal:发送对象发出的信号
receiver:接收信号的对象
slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

系统自带的信号有如下几个

void clicked(bool checked = false)
void pressed()
void released()
void toggled(bool checked )signals inherited from Qwidgetsignals inherited from Q0bject

三、自定义信号和槽

使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。
下面看看使用 Qt 的信号槽:

  1. 首先定义一个学生类和老师类:
    老师类中声明信号 饿了 hungry
signals:void hungury();
  1. 学生类中声明槽 请客 treat
public slots:void treat();
  1. 在窗口中声明一个公共方法下课,这个方法的调用会触发老师饿了这个信号,而响应槽函数学生请客
 void MyWidget::ClassIsOver()
{//发送信号emit teacher->hungury();
}
  1. 学生响应了槽函数,并且打印信息
//自定义槽函数 实现
void Student::eat()
{qDebug() << "该吃饭了!";
}
  1. 在窗口中连接信号槽
teacher = new Teacher(this);
student = new Student(this);
connect(teacher,&Teacher::hungury,student,&Student::treat);

并且调用下课函数,测试打印出 “该吃饭了”

  1. 自定义的信号 hungry带参数,需要提供重载的自定义信号和 自定义槽
void hungury(QString name);  自定义信号
void treat(QString name );    自定义槽
  1. 但是由于有两个重名的自定义信号和自定义的槽,直接连接会报错,所以需要利用函数指针来指向函数地址, 然后在做连接
void (Teacher:: * teacherSingal)(QString) = &Teacher::hungury;
void (Student:: * studentSlot)(QString) = &Student::treat;
connect(teacher,teacherSingal,student,studentSlot);

自定义信号槽需要注意的事项:

  1. 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
  2. 信号和槽函数返回值是 void
  3. 信号只需要声明,不需要实现
  4. 槽函数需要声明也需要实现
  5. 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  6. 使用 emit 在恰当的位置发送信号;
  7. 使用connect()函数连接信号和槽。
  8. 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
  9. 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
  10. 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。

四、完整例程

student.h

#ifndef STUDENT_H
#define STUDENT_H#include <QObject>class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);signals:public slots://早期Qt版本,必须要写到public slots 下,高级版本可以写到 public或者全局下//返回值 void,需要声明,也需要实现//可以有参数,可以发生重载void treat();    // treat 请客的意思void treat(QString foodName);
};#endif // STUDENT_H

teacher.h

#ifndef TEACHER_H
#define TEACHER_H#include <QObject>class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:
// 自定义信号,写道signals下
// 返回值是void 只需要声明,不需要实现
// 可以有参数,可以重载void hungry();void hungry(QString foodName);public slots:
};#endif // TEACHER_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include"teacher.h"
#include"student.h"namespace Ui {class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;Teacher * zt;Student * st;void classIsOver();
};#endif // WIDGET_H

student.cpp

#include "student.h"
#include<QDebug>Student::Student(QObject *parent) : QObject(parent)
{}void Student::treat()
{qDebug()<<"请老师吃饭";
}void Student::treat(QString foodName)
{//qDebug()<<"请老师吃饭,老师要吃:"<<foodName ;  //这行代码输出的是“请老师吃饭,老师要吃:"宫保鸡丁"”//  即 宫保鸡丁 旁边会有引号显示出来//若想去掉引号 需要将变量的QString型 转化为 char *型   先转成QByteArray(.toUtf8()) 再转char *(.data())qDebug()<<"请老师吃饭,老师要吃:"<<foodName.toUtf8().data();   //这样就没有引号了
}

teacher.cpp

#include "teacher.h"Teacher::Teacher(QObject *parent) : QObject(parent)
{}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>//Teacher 类  老师类
//Student 类  学生类
//下课后,老师会触发一个信号,饿了,学生相应信号,请客吃饭Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//创建一个老师对象this->zt=new Teacher(this);//创建一个学生对象this->st=new Student(this);//    //老师饿了 学生请客吃饭的连接
//    connect(zt,&Teacher::hungry,st,&Student::treat);
//    //先用 connect 将老师和学生信号连接起来,再调用下课函数 使老师发出触发信号
//    //调用下课函数
//    classIsOver();//连接带参数的信号和槽//指针->地址   函数指针->函数地址//函数指针:函数返回值类型(*指针变量名)(函数参数列表)void(Teacher::*teacherSignal)(QString)=&Teacher::hungry;void(Student::*studentSlot)(QString)=&Student::treat;connect(zt,teacherSignal,st,studentSlot);//  classIsOver();      //此函数使老师发出 饿了信号//点击一个 下课的按钮,再触发下课QPushButton * btn1 =new QPushButton("下课",this);this->resize(600,400);    //重置窗口大小//点击按钮 触发下课// connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);/*    //无参信号和槽连接void(Teacher::*teacherSignal2)(void)=&Teacher::hungry;void(Student::*studentSlot2)(void)=&Student::treat;connect(zt,teacherSignal2,st,studentSlot2);   //老师发出饿了信号后 学生做出反应
*///信号连接信号
//    connect(btn,&QPushButton::clicked,zt,teacherSignal2);  //点击按钮后 老师响应饿了的信号//断开信号
//    disconnect(zt,teacherSignal2,st,studentSlot2);   //此行代码可以断开 老师和同学之间的连接信号//即老师发出饿了信号后,学生不会做出反应//Lambda表达式
/*    QPushButton *btn3=new QPushButton("Over",this);btn3->move(100,0);[btn](){         //[]里面只添加了btn 表示下面{}里只会识别到btn的相关操作btn->setText("aaaa");// btn3->setText("bbbb");    //识别不到}();      //最后面加一个() 表示调用此表达式
*///mutable关键字 用于修饰值传递的变量,修改的是拷贝,而不是本体
/*  QPushButton *mybtn=new QPushButton("one",this);QPushButton *mybtn2=new QPushButton("two",this);mybtn->move(100,0);mybtn2->move(100,100);int m=10;connect(mybtn,&QPushButton::clicked,this,[m]()mutable{m=100+10;qDebug()<<m;});   //点击“one” 输出m=110,即修改的是拷贝值connect(mybtn2,&QPushButton::clicked,this,[=](){qDebug()<<m;});    //点击“two” 输出m=10,即m的本体没有被修改qDebug()<<m;
*///    int ret=[]()->int{return 1000;}();
//    qDebug()<<"ret = "<<ret;//利用Lambda表达式 实现点击按钮 关闭窗口    最常用的表达式是: [=](){}QPushButton *btn2=new QPushButton("关闭",this);btn2->move(100,0);connect(btn2,&QPushButton::clicked,this,[=](){//        this->close();     //关闭窗口emit zt->hungry("宫保鸡丁");    //点击“关闭”按钮 触发老师饿了信号});}void Widget::classIsOver()
{//下课函数,调用后 出发老师饿了的信号//emit zt->hungry();      //emit 触发自定义信号关键字emit zt->hungry("宫保鸡丁");
}Widget::~Widget()
{delete ui;
}

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

Qt 信号和槽机制( 详解 )相关推荐

  1. Qt信号与槽机制详解1-创建一个带信号和槽的例子

    目录 一.编译一个例子 1.hello.h中的内容 2.hello.cpp的内容 3.main.cpp中的内容 4.tutorial.pro内容 二.moc_hello.cpp文件 1.Q_OBJEC ...

  2. 学习QT之信号槽机制详解

    学习QT之信号槽机制详解 一.Qt信号槽机制 概念:信号槽是Qt框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如:按钮检测到自己被点击了一下,它就会发出一个信号(sig ...

  3. C++框架_之Qt的信号和槽的详解

    目录 C++_之Qt的信号和槽的详解 1.概述 1.1对象树(子对象动态分配空间不需要释放) 2.信号和槽 Qt5 的书写方式:(推荐的使用)★★★★★ Qt4 的书写方式: 3.自定义信号槽 3.1 ...

  4. Qt 信号和槽机制 优点 效率的详解

    一.信号和槽机制 Qt提供了信号和槽机制用于完成界面操作的响应,是完成任意两个Qt对象之间的通信机制. 其中,信号会在某个特定情况或动作下被触发,槽是等同于接收并处理信号的函数. 二..信号和槽机制的 ...

  5. QT信号与槽机制需要注意的问题

    1.信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失.当然这种损失相对来说是比较小的,但是要追求高效率的话,比如实时系统,就要尽可能避免. 2.信号与 ...

  6. Qt信号槽机制详解及案例

    目录 信号槽 标准信号槽 自定义信号槽 信号槽 信号槽是Qt框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signa ...

  7. QT信号和槽机制分析

    QObject这个class是QT对象模型的核心,绝大部分的 QT 类都是从这个类继承而来.这个模型的中心特征就是一个叫做信号和槽(signal and slot)的机制来实现对象间的通讯,你可以把一 ...

  8. Qt基础之四:Qt信号与槽机制原理及优缺点

    目录 一.简介 二.信号和槽 三.信号(signals) 四.槽(slots) 五.在Qt中使用第三方的Signals和Slots 信号

  9. c++基础学习之QT 信号和槽机制的底层实现

    Qt 信号槽的实现 - DevBean Tech World Qt 的信号槽和属性系统基于在运行时进行内省的能力,内省意味着,我们可以列出对象的方法和属性列表,并且能够获取有关它们的所有信息,例如其参 ...

  10. Qt中事件循环机制详解

    问题1:Qt中常见的事件有哪些? 答:鼠标事件(QMouseEvent).键盘事件(QKeyEvent).绘制事件(QPaintEvent).窗口尺寸改变(QResizeEvent).滚动事件(QSc ...

最新文章

  1. 截取年月日在hana中怎么写_写完作业就不学了怎么办?焦虑中的家长不妨先低头看看...
  2. Unique Binary Search Trees
  3. java拖动图片拼图_求教,我的这个拼图程序中的移动图片的改怎么做
  4. TypeError: db.addUser is not a function : @(shell):1:1 ——mongoDB创建新用户名密码的方法...
  5. 微信小程序时代,哪些人能赚到第一桶金
  6. .NET Remoting Security使用小结 – TcpChannel
  7. linux重启后版本变了,linux – 重启后如何使设备映射保持不变?
  8. 技术 产品 团队(上):如何成为超级个体
  9. 【优化算法】蚱蜢优化算法(GOA)【含Matlab源码 1070期】
  10. 用python做一个上位机串口通信_如何用pyserial实现,通过上位机执行python程序从...
  11. 四级网络工程师试题一
  12. android谷歌打印插件下载地址,谷歌浏览器打印插件(Print Plus)
  13. DTU有什么用?是怎样工作的?
  14. 计算机启动过程中按DEL,电脑开机按del之后如何u盘装系统教程
  15. python爬app西瓜视频_python3 scrapy抓取今日头条视频(西瓜视频)
  16. 网页搜索(百度谷歌)你不得不知道的十个小技巧
  17. CPU的四个主要功能
  18. PyCharm Community 2021.2 安装与汉化
  19. blackarch Linux(暗黑Linux)的下载与安装
  20. 知识汇总——50种常用经典电路图

热门文章

  1. keil生成bin文件
  2. 下载安装MinGW-w64详细步骤(c/c++的编译器gcc的windows版,win10真实可用)
  3. mac安装linux时触控板不能用,Linux 下 MacBook 触摸板设置
  4. 世界各个地区WIFI 2.4G及5G信道一览表(附无线通信频率分配表)
  5. 彻底解决Python包下载慢问题
  6. HTML5前端开发实战03-网上花店网页制作
  7. 制造业生产规划与排程的福音—APS系统
  8. 基于MATLAB的线性规划
  9. isis协议配置和详解
  10. 百度大脑技术支持慧译视频字幕系统,为听障学生带来“看得见的声音”