Qt---信号和槽

一、信号和槽机制 

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

连接函数:connect

参数:

        参数1:信号的发送者

        参数2:发送的信号(函数地址)

        参数3:信号的接收者

        参数4:处理的槽函数(函数的地址)

优点:松散耦合

实现点击按钮关闭窗口的案例:

connect(myBtn,&MyPushButton::clicked,this,&myWidget::close);
//connect(myBtn,&QPushButton::clicked,this,&QPushButton::close);使用父类

二、自定义信号和槽 

自定义信号        
        写到signals 下

        返回void
        需要声明,不需要实现

        可以有参数,可以重载

自定义槽函数
        返回void
        需要声明,也需要实现

        可以有参数,可以重载
        写到public slot下或者public或者全局函数        

触发自定义的信号
        emit自定义信号

案例:下课后,老师触发饿了信号,学生响应信号,请客吃饭

student.h

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
    //返回值void,需要声明也需要实现
    //可以有参数,可以发生重载
    void treat();

signals:

};

#endif // STUDENT_H

student.cpp

#include "student.h"
#include<QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat()
{
    qDebug()<<"请老师吃饭";
}

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();

};

#endif // TEACHER_H

teacher.cpp

#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"teacher.h"
#include"student.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    Teacher *zt;
    Student *st;

    void ClassIsOver();
};
#endif // WIDGET_H

widget.cpp

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

//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);

    //调用下课函数
    ClassIsOver();
}

void Widget::ClassIsOver()
{
    //下课函数,调用后触发老师饿了的信号
    emit zt->hungry();
}

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

三、自定义信号和槽发生重载的解决办法 

需要利用函数指针,明确指向函数的地址

void(Teacher:: *teacherSignal)(QString foodName) = &Teacher::hungry;
void(Student:: *studentSlot)(QString foodName) = &Student::treat;

QString转成char*

        .toUtf8()先转为AByteArray

        .date再转为char*         

student.h

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
    //返回值void,需要声明也需要实现
    //可以有参数,可以发生重载
    void treat();

    void treat(QString foodName);//重载版本声明

signals:

};

#endif // STUDENT_H

student.cpp

#include "student.h"
#include<QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat()
{
    qDebug()<<"请老师吃饭";
}

void Student::treat(QString foodName)//重载版本实现
{
    //QString->char *   先转成QByteArray(.toUtf8())再转char *(.data)
    qDebug()<<"请老师吃饭,老师要吃:"<<foodName.toUtf8().data();
}

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);//重载版本

};

#endif // TEACHER_H

teacher.cpp

#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"teacher.h"
#include"student.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    Teacher *zt;
    Student *st;

    void ClassIsOver();
};
#endif // WIDGET_H

widget.cpp

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

//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);

//    //调用下课函数
//    ClassIsOver();

    //连接带参数的信号和槽
    //指针->地址
    //函数指针->函数地址
    void(Teacher:: *teacherSignal)(QString foodName) = &Teacher::hungry;
    void(Student:: *studentSlot)(QString foodName) = &Student::treat;
    connect(zt,teacherSignal,st,studentSlot);
    ClassIsOver();

}

void Widget::ClassIsOver()
{
    //下课函数,调用后触发老师饿了的信号
    //emit zt->hungry();
    emit zt->hungry("宫保鸡丁");//重载版本
}

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

说明:

connect(zt,&Teacher::hungry,st,&Student::treat);

若使用老师饿了的地址&Teacher::hungry和学生请客的地址&Student::treat则不能区分是否带参,故出错(带参和不带参地址一样)

解决方案:

对于函数地址&Teacher::hungry,我们使用函数指针指向函数地址

函数指针定义方式:函数返回值类型(*指针变量名)(函数参数列表);如下:

   void( *teacherSignal)(QString foodName) = &Teacher::hungry;

在声明成员函数的函数地址的时候,要把成员函数的作用域放在指针前面,正确写法如下:

   void(Teacher:: *teacherSignal)(QString foodName) = &Teacher::hungry;

四、信号连接信号

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

//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);

//    //调用下课函数
//    ClassIsOver();

    //连接带参数的信号和槽
    //指针->地址
    //函数指针->函数地址
    void(Teacher:: *teacherSignal)(QString foodName) = &Teacher::hungry;
    void(Student:: *studentSlot)(QString foodName) = &Student::treat;
    connect(zt,teacherSignal,st,studentSlot);
    // ClassIsOver();

    //点击一个下课的按钮,再触发下课
    QPushButton *btn = new QPushButton("下课",this);

    //重置窗口大小
    btn->resize(100,40);

    //点击按钮 触发下课
    //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);

}

void Widget::ClassIsOver()
{
    //下课函数,调用后触发老师饿了的信号
    //emit zt->hungry();
    emit zt->hungry("宫保鸡丁");
}

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

 运行:点击按钮下课则输出,但窗口不会关闭。断开信号不注释,点击按钮则不输出

拓展:
1.信号可以连接信号
2.信号可以连接多个槽函数(点击按钮先输出再关闭窗口[连接close即可])

3.多个信号可以连接一个槽函数
4.信号和槽函数的参数必须―—对应
5.信号的参数个数可以多于槽的参数的个数

五、lambda表达式 

Lambda表达式用于定义并创建匿名的函数对象

[]标识符        匿名函数

        =:值传递

        &:引用传递参数

()参数

{}实现体
mutatle修饰值传递变量,可以修改拷贝出的数据,改变不了本体

返回值()[] ->init {}

labmda表达式最常用        [=](){}

//利用lambda表达式实现点击按钮关闭窗口
    QPushButton *btn2 = new QPushButton;
    btn2->setText("关闭");
    btn2->move(100,0);
    btn2->setParent(this);

    connect(btn2,&QPushButton::clicked,this,[=](){
        this->close();
        emit zt->hungry("宫保鸡丁");
    });

运行,点击下课输出"请老师吃饭",点击关闭输出"请老师吃饭,老师要吃: 宫保鸡丁"同时关闭窗口

输出如下所示:

作业:

两个按钮实现:

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

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

    QPushButton *open_btn = new QPushButton("open",this);
    open_btn->resize(80,30);

    QPushButton *close_btn = new QPushButton("close",this);
    close_btn->resize(80,30);
    close_btn->move(0,100);

    QWidget *window = new QWidget;
    window->setWindowTitle("other_window");
    setWindowTitle("work_window");

    connect(open_btn,&QPushButton::clicked,window,[=](){
        window->show();
    });

    connect(close_btn,&QPushButton::clicked,window,[=](){
        window->close();
    });

}

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

一个按钮实现:

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

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

    QPushButton *btn = new QPushButton("open",this);
    setWindowTitle("work_window");

    QWidget *window = new QWidget;
    window->setWindowTitle("other_window");

    connect(btn,&QPushButton::clicked,window,[=](){
        if(btn->text()=="open")
        {
            btn->setText("close");
            window->show();
        }
        else if(btn->text()=="close")
        {
            btn->setText("open");
            window->close();
        }
    });

}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot自定义初始化sql文件 支持多类型数据库

我在resources目录下有init.sql初始化sql语句 指定sql文件的地址 sql内容如下&#xff1a; /*角色表*/ INSERT INTO #{schema}ccc_base_role (id, create_time, create_user_id, is_delete, role_name, status, update_time, update_user_id) VALUES(b89e30d81acb88448d412…

2024数据分析管理、数字经济与教育国际学术会议(ICDAMDEE2024)

2024数据分析管理、数字经济与教育国际学术会议(ICDAMDEE2024) 会议简介 2024年数据分析管理、数字经济和教育国际学术会议&#xff08;ICDAMDEE 2024&#xff09;将在武汉举行。会议不仅展示了来自世界各地的研究专家围绕数据分析管理、数字经济和教育的最新科研成果&#xf…

C语言 | Leetcode C语言题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; int largestRectangleArea(int* heights, int heightsSize) {int st[heightsSize];int p[2];p[0]-1,p[1]heightsSize;int size0,result0;st[size]0;for(int i1;i<heightsSize;i){ while(size!0&&heights[i]<heights[st[size-1…

Elasticsearch入门基础和集群部署

Elasticsearch入门基础和集群部署 简介基础概念索引&#xff08;Index&#xff09;类型&#xff08;Type&#xff09;&#xff08;逐步弃用&#xff09;文档&#xff08;Document&#xff09;字段&#xff08;Field&#xff09;映射&#xff08;Mapping&#xff09;分片&#x…

从零自制docker-12-【overlayfs】

文章目录 overlayfsexec.Command("tar", "-xvf", busyboxTarURL, "-C", busyboxURL).CombinedOutput()exec.Command格式差异 挂载mount卸载unmount代码地址结果演示 overlayfs 就是联合文件系统&#xff0c;将多个文件联合在一起成为一个统一的…

HTTP1.1的优化措施

3.2 HTTP/1.1 如何优化&#xff1f; 可以从以下三个方面来优化http/1.1协议&#xff1a; 尽量避免发送 HTTP 请求&#xff1b; 在需要发送 HTTP 请求时&#xff0c;考虑如何减少请求次数&#xff1b; 减少服务器的 HTTP 响应的数据大小&#xff1b; 避免发送HTTP请求 对于…

【计算机网络】数据链路层的功能

数据链路层的基本功能&#xff1a; 封装成帧透明传输差错检测 数据链路层使用的信道主要有两种 点对点信道——PPP协议广播信道——CSMA/CD协议(有线局域网)、CSMA/CA协议(无线局域网) 数据链路层所处的地位 从图中可以看出&#xff0c;数据从主机H1送到主机H2需要在路径中…

苍穹外卖项目---------收获以及改进(9-12)

①Spring Task-------实现系统定时任务 概念&#xff1a; 应用场景&#xff1a; 使用步骤&#xff1a; 实现订单超时和前一天派送中的订单的自动任务处理&#xff1a; Component Slf4j public class Mytask {Autowiredprivate OrderServiceimpl orderServiceimpl;/*** 处理订…

05-11 周六 一键完成FastBuild镜像部署功能的开发

05-11 周六 一键完成FastBuild镜像部署功能的开发 时间版本修改人描述2024年5月11日21:50:15V0.1宋全恒新建文档 简介 注&#xff0c;需要提前完成从DockerService到FastBuild主机的免密&#xff0c;因为脚本使用了ssh命令。 博客描述04-22 周日 阿里云-瑶光上部署FastBuild过…

最大子序列的分数

题目链接 最大子序列的分数 题目描述 注意点 n nums1.length nums2.length从nums1和nums2中选一个长度为k的子序列对应的下标对nums1中下标对应元素求和&#xff0c;乘以nums2中下标对应元素的最小值得到子序列的分数0 < nums1[i], nums2[j] < 1000001 < k < …

MVCC 详解

介绍 MVCC&#xff0c;全称 Multi-Version Concurrency Control&#xff0c;即多版本并发控制 MVCC的目的主要是为了提高数据库并发性能&#xff0c;用更好的方式去处理读-写冲突&#xff0c;做到即使有读写冲突时&#xff0c;也能做到不加锁。 这里的多版本指的是数据库中同时…

Django项目运行报错:ModuleNotFoundError: No module named ‘MySQLdb‘

解决方法&#xff1a; 在__init__.py文件下&#xff0c;新增下面这段代码 import pymysql pymysql.install_as_MySQLdb() 注意&#xff1a;确保你的 python 有下载 pymysql 库&#xff0c;没有的话可以使用 pip install pymysql安装 原理&#xff1a;用pymysql来代替mysqlL…

Mysql数据库的基础学习

为什么使用数据库&#xff1f; 1.持久化&#xff1a;将数据保存到可掉电式存储设备中以供使用。 数据库相关概念&#xff1a; DB:数据库&#xff08;Databass&#xff09;即存储数据的仓库&#xff0c;本质是一个文件系统&#xff0c;保存了一系列有组织的数据DBMS:数据库管…

【简单介绍下Sass】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

怎么使用远程桌面传输文件?

微软提供的远程桌面功能是一项强大的工具&#xff0c;可让您在同一网络下远程访问和管理其他计算机。除了远程控制&#xff0c;它还支持文件传输功能&#xff0c;为Windows用户提供了极大的便利。在接下来的内容中&#xff0c;我们将介绍如何使用远程桌面传输文件。 如何从远程…

求正方形中一角四边形的面积

求绿色四边形的面积&#xff1f; 假设大正方形的边长为2a 通过中间的点做十字的辅助线&#xff0c;假设两条辅助线的长度为xy,uv 所以 1/2ay1/2au42① 1/2ay1/2av38② 1/2ax1/2av28③ ①③ 1/2ay1/2au1/2ax1/2av4228 &#xff08;1/2ay1/2av&#xff09;1/2au1/2ax4228 代入…

SeetaFace6人脸特征提取与对比C++代码实现Demo

SeetaFace6包含人脸识别的基本能力&#xff1a;人脸检测、关键点定位、人脸识别&#xff0c;同时增加了活体检测、质量评估、年龄性别估计&#xff0c;并且顺应实际应用需求&#xff0c;开放口罩检测以及口罩佩戴场景下的人脸识别模型。 官网地址&#xff1a;https://github.co…

Hive Transaction事务表(含实现原理)

Hive Transaction事务表 在Hive中&#xff0c;事务表&#xff08;Transactional Tables&#xff09;允许用户执行事务性操作&#xff0c;包括ACID&#xff08;原子性、一致性、隔离性、持久性&#xff09;特性。事务表是在Hive 0.14版本引入的&#xff0c;并且在后续版本中不断…

conan2 基础入门(05)-(静态库动态库)(DebugRelease)

conan2 基础入门(05)-(静态库&动态库)(Debug&Release) 文章目录 conan2 基础入门(05)-(静态库&动态库)(Debug&Release)⭐准备预备文件和Code ⭐静态库&动态库静态库动态库 ⭐Debug&ReleaseReleaseDebug END视频教学settings.yml ⭐准备 本文均在windo…

以太ETH链市值机器人

在数字资产交易市场的浪潮中&#xff0c;如何高效地管理市值、提升交易流动性并保障资金安全&#xff0c;一直是交易所和项目方关注的焦点。市值管理机器人飞机//aishutuyu以太ETH链市值机器人凭借其卓越的功能和强大的安全保障&#xff0c;为数字资产交易市场带来了革命性的变…