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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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;
}
相关文章:

Qt---信号和槽
一、信号和槽机制 所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号…...

POCEXP编写—文件上传案例
POC&EXP编写—文件上传案例 1. 前言2. 文件上传案例2.1. Burp抓包2.2. 基础代码实践2.2.1. 优化代码 2.3. 整体代码2.3.1. 木马测试 1. 前言 之前的文章基本上都是一些相对来说都是验证类的或者说是一些代码执行类的,相对来说都不是太复杂,而这篇会…...

C#知识|上位机UI设计-详情窗体设计思路及流程(实例)
哈喽,你好啊,我是雷工! 上两节练习记录了登录窗体和主窗体的实现过程,本节继续练习内容窗体的实现,以下为练习笔记。 01 详情窗体效果展示: 02 添加窗体并设置属性 在之前练习项目的基础上添加一个Windows窗体,设置名称为:FrmIPManage.cs 设置窗体的边框和标题栏的外…...

目标检测——印度车辆数据集
引言 亲爱的读者们,您是否在寻找某个特定的数据集,用于研究或项目实践?欢迎您在评论区留言,或者通过公众号私信告诉我,您想要的数据集的类型主题。小编会竭尽全力为您寻找,并在找到后第一时间与您分享。 …...
Zotero Word中插入带超链接的参考文献
Zotero 超链接 找了好多原代码,最接近能实施的为: https://blog.csdn.net/weixin_47244593/article/details/129072589 但是,就是向他说的一样会报错,我修改了代码,遇见报错的地方会直接跳过不执行,事后找…...
如何在服务器上下载,解压github上的代码
在github上找到对应仓库,找到平时download zip的地方,右键它,复制链接。在远程的终端里使用wget 链接 命令就可以得到zip了。 解压方法: -c :新建打包文件 -t :查看打包文件的内容含有哪些文件名 -x &…...

BGP学习二:BGP通告原则,BGP反射器,BGP路径属性细致讲解,新手小白无负担
目录 一.AS号 二.BGP路由生成 1.network 2.import-route引入 三.BGP通告原则 1.只发布最优且有效的路由 2.从EBGP获取的路由,会发布给所有对等体 3.水平分割原则 4.IBGP学习BGP默认不发送给EBGP,但如果也从IGP学习到了这条路由,就发…...

Docker学习(带图详细)
一、安装docker 参考官方文档:https://docs.docker.com/engine/install/centos/ 查看系统版本 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# [rootlocalhost ~]# uname -a Linux localhost.localdomai…...
RabbitMQ 如何使用延迟队列
RabbitMQ 如何使用延迟队列 目录 前置条件场景描述RabbitMQ 延迟队列机制实现步骤 1. 安装 RabbitMQ 延迟队列插件2. 创建延迟队列和交换机3. 发布延迟消息4. 消费延迟消息 示例代码 1. 延迟队列配置2. 发布消息的 Producer 代码3. 消费消息的 Consumer 代码 注意事项 前置条…...
【C++】栈和队列
目录 前言 一、stack 1. 栈的定义 2. 成员函数 二、queue 1. 队列的定义 2. 成员函数 三、priority_queue 1. 优先队列的定义 2. 成员函数 前言 栈和队列是STL中很重要的两个容器,栈的特点是先进后出;队列的特点是先进先出。还有优先队列&…...
常用的预编码算法学习
一、概况 预编码算法的常用实现方式有以下几种: 1. 间隔预编码(Interval Pre-coding):该算法将原始数据分成若干个间隔,然后对每个间隔内的数据进行编码。间隔的长度可以根据具体情况进行选择,常见的间隔长度有固定长度和可变长度两种方式。 2. 迭代预编码(Iterative…...
人才培养计划大纲
构建全面而高效的人才培养规划 文章大纲: 引言 人才培养的重要性当前人才培养面临的挑战文章目的与结构人才培养规划的基本概念 定义与内涵人才培养规划与企业战略的关系人才培养规划的基本原则人才培养规划的现状分析 当前人才培养规划的实践情况存在的问题与不足…...
多语言环境下的正则表达式实战:校验整数、小数
在软件开发中,正则表达式是验证用户输入数据格式的强大工具,特别是在处理表单验证时。本文将通过JavaScript、Java、Python、C、Rust、Go、C六种编程语言展示如何使用正则表达式来校验输入是否为整数或小数,特别强调小数点后最多保留两位的场…...

过拟合和欠拟合的学习
1.什么拟合 就是说这个曲线能不能很好地描述某些样本数据,并且拥有较好的泛化能力。 2.什么是过拟合 过拟合就是曲线太过于贴切训练数据的特征了,在训练集上表现得非常优秀,近乎完美的预测/区分了所有得数据,但是在新的测试集上…...

中间件的使用
中间件是全局使用 工厂函数定义中间件 middleware.py # 工厂函数的中间件 def simple_middleware(get_response):def middleware(request):print("在视图函数处理之前执行、、、、、")response get_response(request)print("在视图函数处理之后执行。。。。…...

阿里云OSS权限开通步骤及最佳实践
在阿里云云计算平台中,对象存储服务(OSS)是一种高度可扩展的云存储服务,提供了安全、可靠、低成本的数据存储解决方案。在使用OSS时,正确配置权限是至关重要的,以确保数据的安全性和访问控制。本文将介绍阿…...

【Python贪吃蛇】:编码技巧与游戏设计的完美结合
文章目录 🔥一、运行效果💥二、游戏教程✈1. 导入模块❤️2. 初始化游戏元素☔3. 改变蛇移动的方向👊4. 绘制方块🚀5. 检查蛇头是否在游戏区域内🌈6. 定义蛇的移动函数🎬7. 绑定键盘事件 ⭐三、完整代码 &a…...

2024.5.19 机器学习周报
引言 Abstract 文献阅读 1、题目 X-HRNET: TOWARDS LIGHTWEIGHT HUMAN POSE ESTIMATION WITH SPATIALLY UNIDIMENSIONAL SELF-ATTENTION 2、引言 高分辨率表示是人体姿态估计实现高性能所必需的,随之而来的问题是高计算复杂度。特别地,主要的姿态估…...
母亲节祝福html源码示例
创建一个完整的HTML页面,我可以为您提供一个简单的HTML模板,其中包含一些示例性的祝福语,并添加一些注释以帮助您理解如何扩展内容。 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8&qu…...
微信小程序开发中的权限管理与用户身份验证:守护数据安全与用户体验
微信小程序开发中的权限管理与用户身份验证:守护数据安全与用户体验 引言 在微信小程序开发中,权限管理和用户身份验证是确保数据安全、保护用户隐私以及提供个性化服务的关键环节。本文将深入探讨微信小程序中如何实现权限管理和用户身份验证…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...