三、信号与槽

news2024/12/23 10:35:41

1. 信号槽的定义

信号函数和槽函数是Qt在C++的基础上新增的功能,功能是实现对象之间的通信。
实现信号槽需要有两个先决条件:

  • 通信的对象必须是从QObject派生出来的

    QObject是Qt所有类的基类。

  • 类中要有Q_OBJECT

2. 信号槽的使用

2.1 函数原型

最常用且最基础的信号槽连接函数如下所示:
// 参数1:发送者,信号槽触发的来源的对象
// 参数2:信号函数,发送者的触发动作,使用SIGNAL()包裹
// 参数3:接收者,信号槽触发后执行动作的对象
// 参数4:槽函数,接收者执行的动作,使用SLOT()包裹
QObject::connect(const QObject * sender, 
				    const char * signal, 
				    const QObject * receiver, 
				    const char * method) [static]

按照不同的情况,分为三种情况进行学习:

  • 方式一:自带信号→自带槽
  • 方式二:自带信号→自定义槽
  • 方式三:自定义信号

可以使用disconnect函数断开已经连接的信号槽,参数与connect连接时保持一致。返回值为是否断开成功,如果已经不连接了,则会断开失败,此时不会有任何影响。

2.2 自带信号→自带槽

这种情况下信号函数和槽函数都是Qt内置的,程序员只需要找到对应关系后连接即可。

【例子】点击按钮,关闭窗口。
分析:
发射者:按钮
信号函数:点击
接收者:窗口
槽函数:关闭

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
};

#endif // DIALOG_H
#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("关闭",this);
    btn->move(100,150);

//  发射者:按钮
//	信号函数:点击
//	接收者:窗口
//	槽函数:关闭
    connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}

Dialog::~Dialog()
{
    delete btn;
}

2.3 自带信号→自定义槽

【例子】点击按钮,窗口向右侧移动10个像素,向下移动10个像素,同时输出当前的窗口坐标。
分析:
发射者:按钮
信号函数:点击
接收者:窗口
槽函数:自定义

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;

private slots: // 槽函数
    void mySlot(); // 头文件声明
};

#endif // DIALOG_H
#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("关闭",this);
    btn->move(100,150);
    // 发射者:按钮
//    信号函数:点击
//	接收者:窗口
//	槽函数:自定义
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}

void Dialog::mySlot() // 源文件定义
{
    // 先获得当前的窗口坐标
    int x = this->x();
    int y = this->y();
    // 窗口向右侧移动10个像素,向下移动10个像素
    move(x+10,y+10);
    // 同时输出当前的窗口坐标。
    qDebug() << x+10 << y+10;
}

Dialog::~Dialog()
{
    delete btn;
}

2.4 自定义信号

这种方式主要用于解决复杂问题,所以在本节强行使用。

信号函数具有以下特点:👇

  • 信号函数只有声明,没有定义
  • 信号函数没有权限
  • 声明后只用emit关键字发射
  • 可携带参数

【例子】点击按钮,关闭窗口。
image.png
image.png

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;

private slots:
    void mySlot();

    // 声明信号函数
signals:
    void mySignal(); // 自定义信号
};

#endif // DIALOG_H
#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    btn = new QPushButton("关闭",this);
    btn->move(100,150);

    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
    connect(this,SIGNAL(mySignal()),this,SLOT(close()));
}

void Dialog::mySlot()
{
    // 发射自定义信号
    emit mySignal();
}

Dialog::~Dialog()
{
    delete btn;
}

3. 信号槽传参

信号槽支持参数传递,信号函数可携带参数发送给槽函数。

【例子】点击按钮,按钮上显示点击的次数。
正常的做法不使用信号槽传参:
image.png
dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
    int count; // 点击的次数

private slots:
    void btnClickedSlot(); // 点击按钮的槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent),count(0) // 构造初始化列表
{
    resize(400,400);
    btn = new QPushButton("0",this);
    btn->move(100,200);

    connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
}

void Dialog::btnClickedSlot()
{
    // 显示点击的次数
    count++; // count是成员变量
    // int → 字符串
    QString text =  QString::number(count);
    // 给按钮设置显示内容
    btn->setText(text);
}

Dialog::~Dialog()
{
    delete btn;
}

上面的例子强行增加信号槽传参的语法。
image.png
dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
    int count; // 点击的次数

private slots:
    void btnClickedSlot(); // 点击按钮的槽函数
    void countSlot(int); // 自定义槽函数2

signals:
    // 能发参数的自定义信号
    void countSignal(int);
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent),count(0) // 构造初始化列表
{
    resize(400,400);
    btn = new QPushButton("0",this);
    btn->move(100,200);

    connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
    connect(this,SIGNAL(countSignal(int)),
            this,SLOT(countSlot(int)));
}

void Dialog::btnClickedSlot()
{
   count++;
   // 发射带参数的自定义信号
   emit countSignal(count);
}

/**
 * @brief Dialog::countSlot
 * @param count此数值并非成员变量,而是信号函数发射来的
 */
void Dialog::countSlot(int count)
{
    // int → 字符串
    QString text = QString::number(count);
    // 设置显示
    btn->setText(text);
}

Dialog::~Dialog()
{
    delete btn;
}

4. 总结

  • 槽函数是一种特殊的成员函数
  • 信号函数只有声明,没有定义,因此不能调用
  • 理论上可以传递任意多个信号槽参数
  • 信号的参数个数必须大于等于槽函数的参数个数
  • 信号槽传参的参数类型必须匹配
  • 一个信号函数可以连接多个槽函数,多个信号函数也可以连接看一个槽函数(一对多,多对一)

下面是一个一对多和多对一的例子:
dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn1; // 一对多
    QPushButton* btn2;

private slots:
    void btnClickedSlot1();
    void btnClickedSlot2();
    void btnClickedSlot3();
    void btnClickedSlot4();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    btn1 = new QPushButton("1",this);
    btn1->move(100,100);
    btn2 = new QPushButton("2",this);
    btn2->move(200,200);
    // 一对多
    connect(btn1,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot1()));
    connect(btn1,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot2()));
    // 一对一
    connect(btn2,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot3()));

    // 多对一
    connect(btn1,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot4()));
    connect(btn2,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot4()));
}

void Dialog::btnClickedSlot1()
{
    qDebug() << "a";
}

void Dialog::btnClickedSlot2()
{
    qDebug() << "b";
}

void Dialog::btnClickedSlot3()
{
    // 槽函数也是成员函数
    this->btnClickedSlot1();
    btnClickedSlot2();
}

void Dialog::btnClickedSlot4()
{
    qDebug() << "发射者是谁?";
    // 多对一的情况下如何区分发射者:
    if(btn1 == sender())
    {
        qDebug() << "发射者是btn1";
    }else if(btn2 == sender())
    {
        qDebug() << "发射者是btn2";
    }
}

Dialog::~Dialog()
{
    delete btn1;
    delete btn2;
}

📢上面要注意的点使用了sender()函数,该函数用来返回信号发送者对象的首地址,当有多个发送者对应同一个槽函数时,可以用来判断是谁发的消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1119330.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

免费SSL证书:JoySSL让您的网站更安全

在今天的数字化时代&#xff0c;保护网站和用户信息的安全至关重要。SSL&#xff08;Secure Sockets Layer&#xff09;证书通过加密网站与用户之间的通信&#xff0c;确保数据传输的安全性。让您拥有一个SSL加密的网站是至关重要的&#xff0c;但您可能会担心高昂的费用。不过…

秦丝科技“羽”深大计软学院同行,共庆深圳大学成立40周年

2023年10月21日&#xff0c; 由深圳大学工会主办 &#xff0c; 深圳大学体育学院 、深圳大学后勤部、丽湖校区管委会等单位协办的深圳大学2023年教职工羽毛球联赛-第一场正式举办&#xff1b; 由深圳市秦丝科技有限公司联合头部商户共同赞助的计算机与软件学院取得首场胜利&…

花生好车基于 KubeSphere 的微服务架构实践

公司简介 花生好车成立于 2015 年 6 月&#xff0c;致力于打造下沉市场汽车出行解决方案第一品牌。通过自建直营渠道&#xff0c;瞄准下沉市场&#xff0c;现形成以直租、批售、回租、新能源汽车零售&#xff0c;四大业务为核心驱动力的汽车新零售平台&#xff0c;目前拥有门店…

java基础--transient关键字减少序列化

前置内容 1.序列化 今天在看ArrayList源码的时候看到了这个&#xff0c;我之前应该是看过的&#xff0c;但是忘记了。现在在总结一下。 transient 用在类的属性上&#xff0c;不能修饰其他的。 作用&#xff1a;在序列化的时候transient修饰的属性不能被序列化 用途 在一些…

力扣:盛最多水的容器

题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。 …

【公众号开发】图像文字识别 · 模板消息推送 · 素材管理 · 带参数二维码的生成与事件的处理

【公众号开发】&#xff08;4&#xff09; 文章目录 【公众号开发】&#xff08;4&#xff09;1. 图像文字识别功能1.1 百度AI图像文字识别接口申请1.2 查看文档学习如何调用百度AI1.3 程序开发1.3.1 导入依赖&#xff1a;1.3.2 公众号发来post请求格式1.3.3 对image类型的消息…

【JavaEE】synchronized原理 -- 多线程篇(6)

synchronized原理 1. synchronized具体采用了哪些加锁策略?2. synchronized内部实现策略(内部原理)2.1 偏向锁2.2 轻量级锁与重量级锁 3. synchronized 的其它优化策略3.1 锁消除3.2 锁的粒度 4. 总结 1. synchronized具体采用了哪些加锁策略? synchronized既是悲观锁, 也是…

Power BI 傻瓜入门 4. Power BI:亮点

本章内容包含&#xff1a; 在Power BI Desktop上学习诀窍摄入数据使用模型试用Power BI服务 就像评估一个由多种成分组成的蛋糕一样&#xff0c;Power BI要求其用户熟悉商业智能&#xff08;BI&#xff09;解决方案中的功能。几乎所有与Power BI交互的用户都是从桌面版开始的…

Locust负载测试工具实操

本中介绍如何使用Locust为开发的服务/网站执行负载测试。 Locust 是一个开源负载测试工具&#xff0c;可以通过 Python 代码构造来定义用户行为&#xff0c;避免混乱的 UI 和臃肿的 XML 配置。 步骤 设置Locust。 在简单的 HTTP 服务上模拟基本负载测试。 准备条件 Python…

2021年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 下列代码的输出结果是&#xff1f;&#xff08; &#xff09; x 0x10print(x)A&#xff1a;2 B&#xff1a;8 C&#xff…

NeurIPS 23 Spotlight丨3D-LLM:将3D世界注入大语言模型

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/pdf/2307.12981.pdf 开源代码&#xff1a;https://vis-www.cs.umass.edu/3dllm/ 摘要&#xff1a; 大型语言模型 (LLM) 和视觉语言模型 (VLM) 已被证明在多项任务上…

FPGA的256点FFT调用Quartus IP核实现VHDL傅里叶变换

名称&#xff1a;256点FFT调用Quartus IP核实现傅里叶变换 软件&#xff1a;Quartus 语言&#xff1a;VHDL 代码功能&#xff1a;使用VHDL实现256点FFT&#xff0c;调用Quartus IP核实现傅里叶变换 演示视频&#xff1a;http://www.hdlcode.com/index.php?mhome&cView…

Mysql基础与高级汇总

SQL语言分类 DDL:定义 DML&#xff1a;操作 DCL:控制(用于定义访问权限和安全级别) DQL:查询 Sql方言 ->sql&#xff1a;结构化查询语言 mysql:limit oracle:rownum sqlserver:top 但是存储过程&#xff1a;每一种数据库软件一样SQL语法要求: SQL语句可以单行或多行书写&…

msvcp110.dll无法继续执行代码怎么办?msvcp110.dll丢失的解决方法

msvcp110.dll 丢失通常意味着你的计算机上缺少一个名为 msvcp110.dll 的动态链接库文件。这个文件是 Microsoft Visual C 2010 Redistributable Package 的一个组件&#xff0c;它包含了一些运行时库文件。当你的计算机缺少这个文件时&#xff0c;可能会出现一些问题&#xff0…

有哪些靠谱的获客渠道? 大家都在说精准大数据获客,你了解过没?

如何获取准确、实际的客户信息是众多企业在获客阶段最头疼的问题&#xff0c;想要精准获客就需要了解客户的真实需求&#xff0c;若企业无法满足又无法预估到客户意向&#xff0c;那么将会浪费双方的时间&#xff0c;费力不讨好&#xff0c;企业获客难题是这么多年最难以解决的…

接口自动化测试难点:数据库验证解决方案

接口自动化中的数据库验证&#xff1a;确保数据的一致性和准确性 接口自动化测试是现代软件开发中不可或缺的一环&#xff0c;而数据库验证则是确保接口返回数据与数据库中的数据一致性的重要步骤。本文将介绍接口自动化中的数据库验证的原理、步骤以及示例代码&#xff0c;帮…

关于Mysql中的索引与事务

索引 定义 索引&#xff1a;为了提高查找效率而使用的一种数据结构把数据组织起来&#xff0c;可以把索引理解在书的目录或字典的检索表&#xff08;拼音检索&#xff09; 索引是一种特殊的文件&#xff0c;可以包含着对数据表里的所有记录的引用指针&#xff0c;对表中的一…

jQuery实现输入框提示并点击回显功能呢

html代码: <input type"text" id"affOrganization" name"affOrganization" class"form-control" placeholder"Search..." style"width: 300px" > <div class"search_suggest" id"gov_se…

模拟退火算法(SA)求解旅行商问题(TSP)python

目录 一、模拟退火算法求解TSP&#xff08;city14&#xff09;的python代码 二、city14的运行结果 三、 模拟退火算法求解TSP&#xff08;city30&#xff09;的python代码 四、city30的运行结果 一、模拟退火算法求解TSP&#xff08;city14&#xff09;的python代码 impor…