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

Qt_自定义信号

目录

1、自定义信号的规定

2、创建自定义信号

3、带参数的信号与槽 

4、一个信号连接多个槽 

5、信号与槽的断开 

结语


前言:

        虽然Qt已经内置了大量的信号,并且这些信号能够满足大部分的开发场景,但是Qt仍然允许开发者自定义信号,给开发者提供了足够的DIY设计空间。

1、自定义信号的规定

        Qt中的信号实际上就是函数,因此自定义信号本质就是自定义函数,只不过自定义信号函数的写法要遵循以下三点:

        1、Qt提供了关键字“signals”,自定义信号函数必须写在 “signals” 关键字下边。

        2、自定义信号函数只需要声明,不需要实现,返回值要为void。

        3、自定义信号函数可以有形参,允许重载。

        当然,有了自定义信号函数后还需要拥有将该信号发出的能力,可以使用emit关键字修饰信号函数,表示发送该信号。"emit" 是⼀个空的宏。

2、创建自定义信号

        有了上述的规则后,可以手动创建一个自定义信号,并给该信号连接一个槽函数,槽函数内打印一条语句,运行代码后若输出窗口中打印出了语句说明自定义信号成功创建,具体代码如下。

        1、widget.h的代码如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

signals:
    void mySignal();//自定义信号

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void Print();//槽函数声明

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

         2、widget.cpp的代码如下:

#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QPushButton>

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

    connect(this,&Widget::mySignal,this,&Widget::Print);//连接信号与槽

    emit mySignal();//发送信号
}

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

void Widget::Print()
{
    qDebug()<<"自定义信号调用的自定义槽函数";
}

        运行结果:

        从结果可以看到,槽函数里的语句被打印,说明自定义信号成功被触发且执行了对应的槽函数。 

3、带参数的信号与槽 

        Qt中的信号与槽在代码的层面上都是函数,既然是函数所以他们都可以有形参,不过严格规定信号的参数要与连接的槽的参数类型保持一致,信号的参数多于槽参数都是可以的。当发送该信号时,调用信号所传的实参会传给信号函数的形参,然年信号函数再传递给槽函数,示意图如下:

        代码实现如下,1、widget.h的代码如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

signals:
    void mySignal(QString s);//自定义信号

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void Print(QString s);//槽函数声明

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

        2、widget.cpp的代码如下:

#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QPushButton>

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

    connect(this,&Widget::mySignal,this,&Widget::Print);//连接信号与槽

    emit mySignal("这是一个带有参数的信号");//发送信号
}

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

void Widget::Print(QString s)
{
    qDebug()<<s;
}

        测试结果:

4、一个信号连接多个槽 

        上述的例子中是一个信号连接一个槽函数,因此当发送该信号时会调用一次槽函数。那么当一个信号连接多个槽函数时,发送该信号时具体的调用方式是什么呢?代码测试如下。

         1、widget.h的代码如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

signals:
    void mySignal(QString s);//自定义信号

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void Print(QString s);//槽函数声明1
    void Print2(QString s);//槽函数声明2

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

        2、widget.cpp的代码如下:

#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QPushButton>

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

    connect(this,&Widget::mySignal,this,&Widget::Print);//连接信号与槽
    connect(this,&Widget::mySignal,this,&Widget::Print2);//连接信号与槽

    emit mySignal("这是一个带有参数的信号");//发送信号
}

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

void Widget::Print(QString s)
{
    qDebug()<<s+"槽函数1";
}

void Widget::Print2(QString s)
{
    qDebug()<<s+"槽函数2";
}

        测试结果:

        结果是当一个信号连接多个槽时,发送该信号会调用所有连接的槽的函数,侧面也反映出不仅仅是一个信号可以连接多个槽,一个槽也可以被多个信号连接,只不过这种方式的逻辑就和单个信号连接单个槽的逻辑一样,这里就不再展示代码了

5、信号与槽的断开 

        使⽤disconnect函数即可完成断开,disconnect的⽤法和connect相似,disconnect的形参和connect是一样的,即连接的逻辑和断开的逻辑是一样的。比如在上述代码中,一个信号连接了两个槽函数,使用disconnect函数断开与其中一个槽函数的连接,那么发送信号时只会执行一个槽函数,测试结果如下:

        从结果可以看到,只执行了一个槽函数。 

结语

        以上就是关于自定义信号的讲解,自定义信号虽然用的不多,但是其延申出来的知识可以帮助我们进一步理解信号与槽的细节。 

        最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!   


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

相关文章:

  • 解决conda create速度过慢的问题
  • 计算机网络 (54)系统安全:防火墙与入侵检测
  • ASP.NET Core Web API 创建指南
  • 接口自动化测试
  • vue+高德API搭建前端Echarts图表页面
  • “UniApp的音频播放——点击视频进入空白+解决视频播放器切换视频时一直加载的问题”——video.js、video-js.css
  • 深入浅出:Android屏幕刷新机制
  • 【CanMV K230 AI视觉】 跌倒检测
  • IBM AS/400 数据库介绍、使用及优缺点——详细说明
  • 使用Spring Boot开发自习室预定系统
  • 速盾:cdn加速效果明显吗?
  • 结构型模式-python版
  • uniapp 原生插件开发 UI
  • 模板语法
  • Linux 文件相关知识
  • Qt 布局管理 控件设置
  • 【北京迅为】《STM32MP157开发板使用手册》- 第二十章 Trusted Firmware-A 移植+第二十一章 U-Boot移植
  • 通信工程学习:什么是CSCF会话控制功能、P-CSCF代理会话控制功能、I-CSCF询问会话控制功能、S-CSCF服务会话控制功能
  • Prometheus与Grafana在DevOps中的应用与最佳实践
  • 828华为云征文 | Flexus X的力量,驱动Halo博客在云端飞驰
  • 使用程序方式获取与处理MySQL表数据
  • Uniapp + Vue3 + Vite +Uview + Pinia 实现购物车功能(最新附源码保姆级)
  • Self Refine技术测评:利用Self Refine提高LLM的生成质量
  • 手机如何执行Python
  • 比较stl库的ostringstream与Qt的QString::arg(),QString::number()
  • Transformer理论阶段