qt信号和槽

Qt是一个跨平台的C++图形用户界面应用框架  91年奇趣科技开发

pro工程文件介绍    .pro就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件

QT       += core gui   //Qt包含的模块greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于4版本包含 widgets模块TARGET = Qt_First   //生成exe文件的名称
TEMPLATE = app      //应用程序模板SOURCES += main.cpp\    //源文件mywidget.cppHEADERS  += mywidget.h  //头文件

安装和创建文件方法在上一章已经解决,接下来就是说具体知识总结

其他知识:命名规范

运行 ctrl+r

编译 ctrl+b

注释 ctrl+/

字体缩放 ctrl+鼠标滚轮

整行移动 ctrl+shift+上下箭头

自动对齐 ctrl+i

同名的h和cpp切换 F4

查找关键字 ctrl+f

帮助文档 直接找qt文档,或者左边有帮助

 在Qt程序中,最常用的控件之一就是按钮了,首先我们来看下如何创建一个按钮

按钮 PushButton

QPushButton * btn = new QPushButton; 头文件 #include <QPushButton>//设置父亲//如果想显示时候依赖在当前的窗口中,需要设置父窗btn->setParent(this);//设置文字btn->setText("德玛西亚");//移动位置btn->move(100,100);//第二种创建QPushButton * btn2 = new QPushButton("孙悟空",this);//重新指定窗口大小this->resize(600,400);//设置窗口标题this->setWindowTitle("第一个项目");//限制窗口大小this->setFixedSize(600,400);//就不能拉伸了

QPushButton----------QAbstractButton-----------QWidget  关系为孙父爷关系

上面代码中,一个按钮其实就是一个QPushButton类下的对象,如果只是创建出对象,是无法显示到窗口中的,所以我们需要依赖一个父窗口,也就是指定一个父亲利用setParent函数即可,如果想设置按钮上显示的文字利用setText,移动按钮位置用move

对于窗口而言,我们可以修改左上角窗口的标题setWindowTitle,重新指定窗口大小:resize,或者设置固定的窗口大小setFixedSize

对象树

如图所示,我们言简意赅  树的创建是由上向下,释放时是由下向上,很丝滑

但你如果自己做一个析构函数,你会发现析构顺序和销毁顺序不同

析构函数,先调用父亲但是不执行(就是找到),再调用儿子,执行

Qt窗口坐标体系

坐标体系:

以左上角为原点(0,0),X向右增加,Y向下增加。

对于嵌套窗口,其坐标是相对于父窗口来说的。

 信号和槽机制

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

举例1,人 2.摩擦 3.神灯 4.出神灯   
要做一个连接 将12与34连接起来 结果可以为人在摩擦---神灯后可以出神灯
1.信号发送者(指针)  2.发送的信号 地址 3.信号的接收者 指针 4.处理的槽函数 地址、
connect(myBtn,&MyPushButton::clicked,this,&MyWidget::close);

这个是用好封装的函数调用的地址,用qt帮助文档查找的

 

以下属于自定义信号和槽

widget.h中  
//设置老师和学生Teacher * zt;Student * st;

teacher.h中

    //自定义信号  写到signal下//1.返回值是void//2.只需要声明,不需要实现//3.可以有参数,可以发生重载
signals:void hungry();//空的void hungry(QString foodName);//传参
student.h中
signals: //自定义
//槽函数 写到public slots下,或者public下,或者全局函数,或者lambda
//返回值 void
//需要声明 需要实现
//可以有参数 可以重载
public slots:void treat();void treat(QString foodName);
};

 student.cpp中

void Student::treat()//加作用域
{qDebug()<<"请老师吃饭";
}
void Student::treat(QString foodName)//有参传递
{//QString转为char *//先调用toUtf-8转为QByteArray//再调用data 转为 char*qDebug()<<"请老师吃饭,老师要吃:  "<<foodName.toUtf8().data();//消去引号
}

ps:teacher.cpp中不用添加修改什么

widget.cpp中  这里是重点,反复看里面的代码

#include "widget.h"
#include "QPushButton"
#include "QDebug"
//Teacher老师类  Student学生类
//下课后,老师会发出饿了的信号,学生进行响应,请老师吃饭Widget::Widget(QWidget *parent): QWidget(parent)
{this->zt=new Teacher(this);//在窗口中连接信号槽this->st=new Student(this);//连接信号和槽
//    connect(this->zt,&Teacher::hungry,this->st,&Student::treat);//连接有参的信号和槽//函数指针指向函数地址
//    void(Teacher:: * teacherSignal)(QString)=&Teacher::hungry;
//    void(Student:: * studentSlot)(QString)=&Student::treat;
//    connect(this->zt,teacherSignal,this->st,studentSlot);//按键QPushButton *btn=new QPushButton;btn->setParent(this);btn->setText("下课");//无参void(Teacher:: * teacherSignal2)()=&Teacher::hungry;void(Student:: * studentSlot2)()=&Student::treat;connect(this->zt,teacherSignal2,this->st,studentSlot2);
//      老师饿了(--学生请客)//信号和槽拓展//1.信号连接信号                                //无参connect(btn,&QPushButton::clicked,this->zt,teacherSignal2);
//                              bool        >=       0//连接方式  点击按钮--老师饿了(--学生请客)//2.一个信号可以连接多个槽函数//3.多个信号可以绑定同一个槽函数//4.信号和槽的参数类型,必须是一一对应  传的信号是宫保鸡丁,接受的也必须是宫保鸡丁QString--QSt//5.信号的参数个数可以多于槽函数,反之不可以   例如(QString,int)---(QString)正确//6.相同个数的参数类型也要一一对应//7.可以利用disconnect断开信号槽的连接
//  disconnect(btn,&QPushButton::clicked,this->zt,teacherSignal2);断前面
//  disconnect(this->zt,teacherSignal2,this->st,studentSlot2);断后面//下课函数调用
//    classISOver();//连接作用//lanbda表达式QPushButton *btn2=new QPushButton;btn2->move(100,0);btn2->setParent(this);btn2->setText("aaa");//函数体内可以使用lambda所在范围内所有可见的局部变量[=](){btn2->setText("bbb");}();//->返回值类型int num=[]()->int{return 1000;}();qDebug()<<"num"<<num;//[=](){}推荐使用QPushButton * btn3=new QPushButton;btn3->setParent(this);btn3->move(200,200);btn3->setText("aaa");connect(btn3,&QPushButton::clicked,this,[=]()//优化了上面信号连接信号的有参{btn3->setText("ccc");this->st->treat("鱼香肉丝");//直接调槽函数   在connect中调另一个函数this->close();});//用=正确(复制一个,间接改)用&错误!(直接修改)}
void Widget::classISOver(){//触发自定义信号emit this->zt->hungry();emit this->zt->hungry("宫保鸡丁");
}
Widget::~Widget()
{
}

挑里面两个重点代码说说

这里是无参信号连接槽
  this->zt=new Teacher(this);//在窗口中连接信号槽this->st=new Student(this);//连接信号和槽connect(this->zt,&Teacher::hungry,this->st,&Student::treat);

这里是有参信号连接槽

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

注意:题目前提是

下课后,老师会发出饿了的信号,学生进行响应,请老师吃饭

所以添加一个触发信号,下课了,老师肚子饿了,学生请客吃饭,符合逻辑。

void Widget::classISOver(){//触发自定义信号emit this->zt->hungry();emit this->zt->hungry("宫保鸡丁");
}

信号连接信号    connect代码,点一下按钮,连接老师饿了,回到上面几行,老师饿了,学生请客

    //无参void(Teacher:: * teacherSignal2)()=&Teacher::hungry;void(Student:: * studentSlot2)()=&Student::treat;connect(this->zt,teacherSignal2,this->st,studentSlot2);
//      老师饿了(--学生请客)//信号和槽拓展//1.信号连接信号                                //无参connect(btn,&QPushButton::clicked,this->zt,teacherSignal2);
//                              bool        >      0//连接方式  点击按钮--老师饿了(--学生请客)

这里只能是无参调用,因为clicked为bool类型,如果后面teacherSignal2得到了参数   如:

emit this->zt->hungry("宫保鸡丁");

connect(btn,&QPushButton::clicked,this->zt,teacherSignal2);将此代码理解为clicked是bool类型为1,是信号,teacherSingnal2为槽函数,当传入参数时QString(宫保鸡丁)就为失败

因为

   1一个信号可以连接多个槽函数    2.多个信号可以绑定同一个槽函数  3.信号和槽的参数类型,必须是一一对应  传的信号是宫保鸡丁,接受的也必须是宫保鸡丁QString--QString4.信号的参数个数可以多于槽函数,反之不可以   例如(QString,int)---(QString)正确              5.相同个数的参数类型也要一一对应     
6.可以利用disconnect断开信号槽的连接

自定义信号槽需要注意的事项

  1. 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
  2. 信号和槽函数返回值是 void
  3. 信号只需要声明,不需要实现
  4. 槽函数需要声明也需要实现
  5. 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  6. 使用 emit 在恰当的位置发送信号;
  7. 使用connect()函数连接信号和槽。
  8. 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
  9. 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
  10. 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。

信号槽的拓展

  1. 一个信号可以和多个槽相连

如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。

  1. 多个信号可以连接到一个槽

只要任意一个信号发出,这个槽就会被调用

  1. 一个信号可以连接到另外的一个信号

当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。

  1. 槽可以被取消链接

这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽

  1. 信号槽可以断开

利用disconnect关键字是可以断开信号槽的

  1. 使用Lambda 表达式

在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。

在连接信号和槽的时候,槽函数可以使用Lambda表达式的方式进行处理。后面我们会详细介绍什么是Lambda表达式

 

那人问了,那该怎么办呢?

lambda函数 

 引入lambda函数         Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。

[capture](parameters) mutable ->return-type//Lambda表达式的基本构成

{

statement

}

[函数对象参数](操作符重载函数参数)mutable ->返回值{函数体}

函数对象参数;

[],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。函数对象参数有以下形式          

  1. 空。没有使用任何函数对象参数。
  2. =。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。

        3.&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。

 那么如何实现lambda   实现信号连接信号有参呢?

     //lanbda表达式QPushButton *btn2=new QPushButton;btn2->move(100,0);btn2->setParent(this);btn2->setText("aaa");//函数体内可以使用lambda所在范围内所有可见的局部变量[=](){btn2->setText("bbb");}();//->返回值类型int num=[]()->int{return 1000;}();qDebug()<<"num"<<num;//[=](){}推荐使用QPushButton * btn3=new QPushButton;btn3->setParent(this);btn3->move(200,200);btn3->setText("aaa");connect(btn3,&QPushButton::clicked,this,[=]()//优化了上面信号连接信号的有参{btn3->setText("ccc");this->st->treat("鱼香肉丝");//直接调槽函数   在connect中调另一个函数this->close();});//用=正确(复制一个,间接改)用&错误!(直接修改)}

精华代码在这


     connect(btn3,&QPushButton::clicked,this,[=]()//优化了上面信号连接信号的有参
     {
         btn3->setText("ccc");
        this->st->treat("鱼香肉丝");//直接调槽函数   在connect中调另一个函数
         this->close();

     });//用=正确(复制一个,间接改)用&错误!(直接修改)

直接调槽函数   在connect中调另一个函数 ,槽函数也是函数,所以在connect中直接调用

connect中加了一个lambda函数

另外有一个重点:

在lambda[]用=正确(复制一个,间接改)用&错误!(直接修改)

完结,收工 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024.1.2 Redis 数据类型 Stream、Geospatial、HyperLogLog、Bitmaps、Bitfields 简介

目录 引言 Stream 类型 Geospatial 类型 HyperLogLog 类型 Bitmaps 类型 Bitfields 类型 引言 Redis 最关键&#xff08;应用广泛、频繁使用&#xff09;的五个数据类型 StringListHashSetZSet 下文介绍的数据类型一般适合在特定的场景中使用&#xff01; Stream 类型 St…

强化学习的数学原理学习笔记 - 基于模型(Model-based)

文章目录 概览&#xff1a;RL方法分类基于模型&#xff08;Model-Based&#xff09;值迭代&#xff08;Value Iteration&#xff09;&#x1f7e6;策略迭代&#xff08;Policy Iteration&#xff09;&#x1f7e1;截断策略迭代&#xff08;Truncated Policy Iteration&#xff…

EasyRecovery2024永久免费版电脑数据恢复软件

EasyRecovery是一款操作安全、价格便宜、用户自主操作的非破坏性的只读应用程序&#xff0c;它不会往源驱上写任何东西&#xff0c;也不会对源驱做任何改变。它支持从各种各样的存储介质恢复删除或者丢失的文件&#xff0c;其支持的媒体介质包括&#xff1a;硬盘驱动器、光驱、…

特征工程(一)

特征工程&#xff08;一&#xff09; 什么是特征工程 简单来讲将数据转换为能更好地表示潜在问题的特征&#xff0c;从而提高机器学习性能 特征工程包含的内容 转换数据的过程特征更好地表示潜在问题提高机器学习性能 数据和机器学习的基础知识 数据基础 以下为数据的一…

计算机网络(超级详细笔记)

使用教材计算机网络&#xff08;第8版&#xff09;&#xff08;谢希仁&#xff09; 第一章&#xff1a;概述 第二章&#xff1a;物理层 第三章&#xff1a;数据链路层 第四章&#xff1a;网络层 第五章&#xff1a;运输层 第六章&#xff1a;应用层 目…

适合培训协会搭建的培训机构管理系统开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 培训学校教务管理系统是培训机构数字化管理的必备系统&#xff0c;该系统功能大大提升机构办学的管理效率、提升机构在家长心中的专业度&#xff0c;市面上的培训机构管理系统收费越来越贵&#xff0c;为了给协会内培…

【陈老板赠书活动 - 21期】- Python树莓派编程从零开始(第3版)

陈老老老板&#x1f9d9;‍♂️ &#x1f46e;‍♂️本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f934;本文简述&#xff1a;活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f473;‍♂️上一篇文章&#xff…

微信小程序实战-01翻页时钟-1

文章目录 前言需求分析功能设计界面设计界面结构设计界面样式设计 逻辑设计 单页功能实现运行结果 前言 我经常在手机上用的一款app有一个功能是翻页时钟&#xff0c;基于之前学习的小程序相关的基础内容&#xff0c;我打算在微信小程序中也设计一个翻页时钟功能&#xff0c;J…

ArcGIS小技巧|四种计算图斑面积的方法

ArcGIS中有多种方法可计算出图斑面积&#xff0c;本文总结了四种方法&#xff0c;是否可堪称史上最全&#xff1f; 1、计算几何 这是最适合非专业人士的方法&#xff0c;直接利用ArcGIS中的计算几何功能进行计算。 a、首先添加一double类型字段&#xff0c;用来存储面积数值…

移动通信原理与关键技术学习(2)

1.多径信道滤波器表示&#xff0c;多径信道可以认为是线性时变滤波器&#xff0c;接收信号为发送信号与信道冲激响应的卷积。 2.调制就是对信号源的信息进行处理加到载波上&#xff0c;使其变为适合于信道传输的形式的过程&#xff0c;就是使载波随信号而改变的技术。 3.进行调…

基于 Python+Neo4j+医药数据,构建了一个知识图谱的自动问答系统

知识图谱是目前自然语言处理的一个热门方向。目前知识图谱在各个领域全面开花&#xff0c;如教育、医疗、司法、金融等。 本项目立足医药领域&#xff0c;以垂直型医药网站为数据来源&#xff0c;以疾病为核心&#xff0c;构建起一个包含7类规模为4.4万的知识实体&#xff0c;…

【MIdjourney】图像角度关键词

本篇仅是我个人在使用过程中的一些经验之谈&#xff0c;不代表一定是对的&#xff0c;如有任何问题欢迎在评论区指正&#xff0c;如有补充也欢迎在评论区留言。 1.侧面视角(from side) 侧面视角观察或拍摄的主体通常以其侧面的特征为主要焦点&#xff0c;以便更好地展示其轮廓…

Linux文件系统和日志分析

一、inode表结构 1. inode表 inode号在同一个设备上是唯一的。 inode号是有限资源&#xff0c;它的大小和磁盘大小有关。 访问文件的基本流程 根据文件夹的文件名和inode号的关系找到对应的inode表&#xff0c;再根据inode表&#xff08;属主 属组&#xff09;当中的指针找到磁…

Python 全栈体系【四阶】(十一)

第四章 机器学习 机器学习&#xff1a; 传统的机器学习&#xff1a;以算法为核心深度学习&#xff1a;以数据和计算为核心 感知机 perceptron&#xff08;人工神经元&#xff09; 可以做简单的分类任务掀起了第一波 AI 浪潮 感知机不能解决线性不可分问题&#xff0c;浪潮…

c# 学习笔记 - 委托(Delegate)

文章目录 1. 委托1.1 委托概述1.2 委托使用1.3 委托的传播 2. 匿名方法2.1 匿名方法概述2.2 匿名方法 1. 委托 1.1 委托概述 委托简介 委托就是对方法的引用&#xff0c;可以理解为例如整型变量的容器可以存储整形数据&#xff0c;委托就是某种方法的容器&#xff0c;可以用来…

解决Android AAPT: error: resource android:attr/lStar not found. 问题

错误信息 /xxx/gjc/.gradle/caches/transforms-2/files-2.1/930c42acd29d295ce5bc495c3b84423e/core-1.9.0/res/values/values.xml:104:5-113:25: AAPT: error: resource android:attr/lStar not found. not found 资源位置 场景 原Android studio中的项目都是在git上面拉的老项…

React Admin 前端脚手架之ant-design-pro

文章目录 一、React Admin 前端脚手架选型二、React Admin 前端脚手架之ant-design-pro三、ant-design-pro使用步骤四、调试主题五、常用总结(持续更新)EditableProTable组件 常用组件EditableProTable组件 编辑某行后,保存时候触发发送请求EditableProTable组件,添加记录提…

关于简单的数据可视化

1. 安装数据可视化必要的openpyxl、pandas&#xff0c;matplotlib等软件包 使用清华源&#xff0c;命令如下&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn pandaspip install -i https://pypi.tuna.tsingh…

uni-app 从入门到精通 3天快速掌握 文字版 学习专栏

大家好&#xff0c;我是java1234小锋老师。 近日锋哥又卷了一波课程&#xff0c;uni-app 从入门到精通 3天快速掌握教程&#xff0c;文字版视频版。三天掌握。 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从…

7.27 SpringBoot项目实战 之 整合Swagger

文章目录 前言一、Maven依赖二、编写Swagger配置类三、编写接口配置3.1 控制器Controller 配置描述3.2 接口API 配置描述3.3 参数配置描述3.4 忽略API四、全局参数配置五、启用增强功能六、调试前言 在我们实现了那么多API以后,进入前后端联调阶段,需要给前端同学提供接口文…