当前位置: 首页 > article >正文

【Qt】信号和槽机制

目录

1.信号和槽的理解

Qt内置类的继承关系

2.connect方法

参数

使用示例

2.1 disconnect断开信号槽

2.2 查看内置类型的信号和槽

3.自定义槽函数

3.1 代码方式自定义槽函数

3.2 图形化方式自定义槽函数

4.自定义信号

5.带参数的信号和槽

6.信号和槽的关联关系

7.信号和槽机制的意义

8.lamda表达式作槽函数


1.信号和槽的理解

信号的三个要素

1.信号源 2.信号类型 3.信号处理方法

Qt

信号源:由哪个控件发出信号

信号类型:用户不同的操作,会触发不同的信号(如:点击按钮,触发点击信号;在输入框移动光标,触发移动光标信号;勾选复选框,选择一个下拉框,都会触发不同信号)

信号处理方式:槽(slot)-》函数

槽函数,本质上就是信号处理的回调函数。

connect()

由QObject提供的静态成员函数。

Qt内置类的继承关系

Qt内置类的都有继承关系,所以继承Qbject的所有子类都能调用connect方法。

2.connect方法

1.介绍

connect (const QObject *sender, 
 const char * signal ,
 const QObject * receiver , 
 const char * method , 
 Qt::ConnectionType type = Qt::AutoConnection )

参数

使用前四个参数
1.信号源

2.信号类型

3.接收者

4.处理方法

参数1和参数2 、参数3和参数4 类型必须匹配:1.类对象指针 2.内置信号指针父类信号的指针


参数2和参数4,为函数指针。

查看我们传入数据的类型:

函数指针类型void(*)()

,void(*)()

查看函数声明:

我们都知道,不同类型的指针不能相互赋值(除非强转)。

原因,该声明为旧版本声明,传参方法有所不同,需要搭配SIGNAL宏和SLOT宏来传参

如:connect(button,SIGNAL(&QPushButton::ckicked),this,SLOT(&Widget::close));

宏的作用是,将函数指针类型,转为char*类型。

从Qt5开始对写法进行了简化,不再需要使用宏了,而是为connect提供函数重载

重载函数的2,4参数为泛型参数,允许传入任意类型

版本问题:
Qt5的connect支持类型检测,4中connect需要搭配SIGNAL和SLOT宏使用,并不支持类型是否一致的检测。


使用示例

实现点击按钮关闭窗口

close是Qwidget内置的槽函数,所以继承自QWidget的Widget类也能调用该函数。

2.1 disconnect断开信号槽

参数和connect基本一致。

2.2 查看内置类型的信号和槽

那么,close槽和clicked信号,如何得知呢?

看文档,F2

clicked:点击鼠标(按下+释放鼠标)

pressed:按下

released:释放

toggled:状态切换,复选框

3.自定义槽函数

语法:

1.可以作为普通成员函数声明定义

2.public slots: 函数声明 

3.1 代码方式自定义槽函数

添加一个成员函数,作为自定义信号处理的槽函数。

alt+回车,添加函数定义

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button=new QPushButton(this);
    button->setText("按钮");
    button->move(100,100);

    connect(button,&QPushButton::clicked,this,&Widget::HandelClicked);


}


Widget::~Widget()
{
    delete ui;
}

void Widget::HandelClicked()
{
//按下按钮,修改窗口标题
    this->setWindowTitle("按钮已经按下");
}

3.2 图形化方式自定义槽函数

1.右键,转到槽,选择信号

自动添加函数声明和定义

2.定义槽函数


原理:如何实现关联信号和槽?

ui文件生成的头文件内部调用,关联函数。

该函数自动将信号和符合命名规则的槽函数关联。

若不符合规则,则报错,无匹配函数。

规则:

函数名on_控件ObjectName属性_信号

4.自定义信号

语法:1.signals:  2.emit触发信号、

注意必须先关联信号和槽,才能emit触发信号,否则若无关联的槽就触发信号,不会调用任何回调来处理信号。

信号函数只需要声明,不需要实现。

示例:

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //关联自定义的信号和槽
    connect(this,&Widget::MySignal,this,&Widget::MySlots);

    //发射信号
    emit MySignal();
}

Widget::~Widget()
{
    delete ui;
}

//定义我的槽函数
void Widget::MySlots()
{
   qDebug()<<"我的信号和槽";
}

5.带参数的信号和槽

要求:

1.参数类型必须匹配

2.个数要求,信号参数必须等于,或大于,关联的槽函数的参数个数

支持信号和槽的重载。

目的:让同一个信号,可以关联更多的槽函数。

示例:重载带参数的信号和槽

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //初始化函数指针
    void (Widget::*signal_p)(QString)=&Widget::MySignal;
     void (Widget::*slot_p)(QString)=&Widget::MySlots;

    //关联自定义的信号和槽
    connect(this,signal_p,this,slot_p);

    //发射信号
    EmitSignal();


}

Widget::~Widget()
{
    delete ui;
}

//定义我的槽函数
void Widget::MySlots()
{
    qDebug()<<"我的信号和槽";
}

void Widget::MySlots(QString text)
{
    qDebug()<<"带参槽函数被调用:"<<text;
}

void Widget::EmitSignal()
{
    emit MySignal("emit传递的信号参数");
}

6.信号和槽的关联关系

  • 一个信号,一个槽
  • 多个信号,同一个槽
  • 一个信号,多个槽

  • 一个信号关联一个信号

这种情况下,一个信号触发后,另一个信号会自动发出。

这种方式通常用于将一个信号的发生转发为另一个信号,简化多个信号的触发。

示例:


7.信号和槽机制的意义

1.解耦:信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自己,Qt的信号槽机制保证了信号与槽函数的调⽤。

2.多对多

缺点:与回调函数相⽐,信号和槽稍微慢⼀些。

(定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队)

设计初衷是为了信号和槽多对多,但实际设计中,我们还是经常以一对一的方式使用信号槽。

8.lamda表达式作槽函数

Qt5:无需手动添加编译选项。

Qt5以下版本:需采用C++11标准编译文件,在".pro"⽂件中添加: CONFIG += C++11 。

注意捕捉变量的生命周期问题,=拷贝值的方式捕捉。


http://www.kler.cn/a/460336.html

相关文章:

  • C# 标准数字格式字符串
  • Windows系统提示ffmpeg.dll丢失怎么解决?
  • liunx下载gitlab
  • HTML 字符编码
  • 慧集通iPaaS集成平台低代码培训-基础篇
  • 框架(Mybatis基础配置)
  • 【MyBatis-Plus】让 MyBatis 更简单高效
  • 【Kafka 消息队列深度解析与应用】
  • 基于zynq在linux下的HDMI实战
  • labelme2yolov8-seg 草稿()
  • 头歌python:多进程和多线程
  • 年会头投票小游戏
  • 强化学习(1)
  • filament的材质系统
  • io多路复用, select, poll, epoll
  • 计算机因进程结束导致白屏
  • MySQL的多表查询与事务
  • node.js之---EventEmitter 类
  • 数据结构(哈希表)
  • 如何在TikTok上成功推广国际品牌?
  • HTML——20 自定义属性
  • 改进爬山算法之七:动态邻域爬山法(Dynamic Neighborhood Hill Climbing,DNHC)
  • 【项目实战】Apache JMeter HTTP 接口测试
  • CP AUTOSAR标准之FlexRayDriver(AUTOSAR_SWS_FlexRayDriver)(更新中……)
  • ROS2+OpenCV综合应用--9. AprilTag标签码识别
  • 深度学习中的迁移学习:如何利用现有模型加速训练?