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.cpp
	
HEADERS  += 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--QString
 4.信号的参数个数可以多于槽函数,反之不可以   例如(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[]用=正确(复制一个,间接改)用&错误!(直接修改)

完结,收工 

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

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

相关文章

实时语义分割模型PP-LiteSeg论文解读

paper&#xff1a;PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model official implementation&#xff1a;https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.8/paddleseg/models/pp_liteseg.py 本文的创新点 提出了一种灵活的轻量级解码器&#xf…

OCS2 入门教程(四)- 机器人示例

系列文章目录 前言 OCS2 包含多个机器人示例。我们在此简要讨论每个示例的主要特点。 System State Dim. Input Dim. Constrained Caching Double Integrator 2 1 No No Cartpole 4 1 Yes No Ballbot 10 3 No No Quadrotor 12 4 No No Mobile Manipul…

虾皮一键铺货软件:如何使用一键铺货软件在Shopee平台上上架商品

在如今竞争激烈的电商市场中&#xff0c;卖家们都希望能够快速上架商品&#xff0c;以节省时间和精力&#xff0c;并提高销售效率。而在Shopee&#xff08;虾皮&#xff09;平台上&#xff0c;一键铺货软件成为了许多卖家的首选工具。这些软件不仅可以帮助卖家快速将商品批量上…

Python Asyncio网络编程方法全面解析与实战应用!

更多Python学习内容&#xff1a;ipengtao.com Python的asyncio库是一种强大的异步编程工具&#xff0c;它使得编写高效的网络应用程序变得更加容易。在本文中&#xff0c;我们将深入探讨使用asyncio进行网络编程的方法&#xff0c;包括异步IO、协程、事件循环等方面的内容&…

Android学习(一):Android Studio安装与配置

Android学习&#xff08;一&#xff09;&#xff1a;Android Studio安装与配置 一、安装 下载地址 下载zip文件&#xff0c;免安装。 二、下载资源 启动后&#xff0c;出现该弹框&#xff0c;点击Cancel。 点击Next 默认&#xff0c;点击Next。 点击Next。 点击Finish 开始…

Danil Pristupov Fork(强大而易用的Git客户端) for Mac/Windows

在当今软件开发领域&#xff0c;团队协作和版本控制是非常重要的方面。在这个过程中&#xff0c;Git成为了最受欢迎的版本控制工具之一。然而&#xff0c;对于Git的使用&#xff0c;一个好的客户端是至关重要的。 今天&#xff0c;我们要为大家介绍一款强大而易用的Git客户端—…

大模型迎来“AppStore时刻”,OpenAI给2024的新想象

一夜之间&#xff0c;OpenAI公布了多个重磅消息&#xff0c;引发市场关注。 钛媒体App 1月5日消息&#xff0c;今晨&#xff0c;OpenAI公司向所有GPT开发者们发布一封邮件称&#xff0c;下周将上线自定义的“GPT Store”商店&#xff0c;这有望推动ChatGPT开发者生态不断完善。…

完美版视频网站模板 – 苹果CMS v10大橙子vfed主题

源码下载&#xff1a; https://download.csdn.net/download/m0_66047725/88700504 这次提供的大橙子 vfed 模板 已经完美&#xff0c;只去除了授权验证和正版主题神秘后门&#xff0c;不影响任何功能体验性。主题优化&#xff1a;全站响应式自带主题设置面板自带联盟资源库大全…

Docker nginx容器代理播放m3u8视频文件(HLS)

文章目录 Docker Nginx容器代理播放M3U8文件教程获取Nginx Docker镜像设置Nginx配置文件用 ffmpeg 将 MP4 文件转换成 m3u8 文件运行Docker容器测试M3U8流其他问题我用vlc都能播放http://192.168.121.50/forest4kTest.m3u8和http://192.168.121.50/forest4kTest.mp4&#xff0c…

MediaPipeUnityPlugin(最新版)摇摆拳人脸识别

1、从https://github.com/homuler/MediaPipeUnityPlugin 下载Release Package 目前是MediaPipeUnity.0.12.0.unitypackage 2、导入Unity工程 3、打开Face Detection场景&#xff0c;做一些设置修改 1、打开Bootstrap&#xff0c;图像源改成Video&#xff0c;把Solution拖拽到…

蓝桥杯备赛系列 高精度 acwing版

前言 hello&#xff0c;好久不见。元旦玩过后该收心了&#xff0c;我也倒计时一下蓝桥杯考试时间&#xff0c;大家一起复习&#xff0c;一起登顶。今天讲解高精度算法。 这个算法其实是给学c同学讲的&#xff0c;因为python自带高精度所以不需要&#xff0c;且我讲到所有内容…

STM32_HAL Freertos按键控制LED

设置GPIO引脚 根据电路图&#xff0c;K0为用户按键&#xff0c;连接在PA0引脚&#xff0c;当K0按下时接地&#xff0c;引脚电平低电平。在CubeMX中设置PA0&#xff0c;将IO设置为输入&#xff0c;上拉&#xff08;上拉外部悬空时&#xff0c;引脚为高电平&#xff09;。 添…

物联网云平台源码,Spring Cloud智慧工地源码,建筑施工智能化管理

智慧工地以物联网云平台为核心&#xff0c;基于智慧工地物联网云平台与现场多个子系统的互联&#xff0c;实现现场各类工况数据采集&#xff0c;存储、分析与应用。通过接入智慧工地物联网云平台的多个子系统板块&#xff0c;根据现场管理实际需求灵活组合&#xff0c;实现一体…

Mac Parallels19.1.0 Install CentOS7.9

0、资源准备 # centos7.9镜像一份 链接: https://pan.baidu.com/s/1acIjUnsTGhk_2cYCZLSoGg?pwd6666 提取码: 6666 --来自百度网盘超级会员v7的分享1、打开PD 2、选择镜像进行安装 指定镜像名称 创建 进行密码设置 安装目的地点开后直接点击完成 网络和主机名称 开…

cad快速看图软件免费版(手机在线cad快速看图)

cad快速看图软件免费版(手机在线cad快速看图) 很多机械设计师日常工作过程中涉及到多种格式的cad图纸&#xff0c;cad图纸大多都需要cad设计软件才能打开&#xff0c;然而很多小伙伴并没有下载相应的cad设计软件&#xff0c;这种情况下如何进行cad快速看图呢&#xff1f; 今天…

【开源项目】WPF 扩展组件 -- Com.Gitusme.Net.Extensiones.Wpf

一、项目简介 Com.Gitusme.Net.Extensiones.Wpf 是一款 Wpf 扩展组件。基于.Net Core 3.1 开发&#xff0c;当前最新 1.0.1 版本。包含 核心扩展库&#xff08;Com.Gitusme.Net.Extensiones.Core&#xff09;、视频渲染&#xff08;Com.Gitusme.Media.Video&#xff09;、串口…

刚学C/C++,使用的是CLion,想要在同一个项目里面运行多个相互独立脚本?

前言&#xff1a; 正常来说&#xff0c;一般一个项目只会有一个程序入口点。C和C程序的入口点是main函数。在一个项目中&#xff0c;只能有一个main函数&#xff0c;否则编译器会不知道从哪个main函数开始执行。 但是&#xff0c;作为初学者&#xff0c;我就是想用CLio…

Redis(Nosql数据库)

目录 一.SQL 与 NoSQL 的区别&#xff1f; 二.Redis Redis 为什么那么快&#xff1f; 三.Redis的安装 安装redis&#xff1a; 创建redis工作目录&#xff1a; 修改redis配置文件&#xff1a; redis-cli 命令行工具&#xff1a; redis-benchmark 测试工具&#xff1a; …

插槽slot涉及到的样式污染问题

1. 前言 本次我们主要结合一些案例研究一下vue的插槽中样式污染问题。在这篇文章中&#xff0c;我们主要关注以下两点: 父组件的样式是否会影响子组件的样式&#xff1f;子组件的样式是否会影响父组件定义的插槽部分的样式&#xff1f; 2. 准备代码 2.1 父组件代码 <te…

Linux驱动开发(1)-最简单的字符设备驱动开发例子

1.简介 字符设备驱动&#xff1a;按照字节流进行读写操作的设备&#xff0c;例如点灯、按键、IIC、SPI、LCD。 Linux系统中一切皆文件&#xff0c;驱动加载成功&#xff0c;就会在/dev目录生成文件&#xff0c;对文件操作&#xff0c;则可实现对硬件操作。应用程序运行在用户…