Qt第二课----信号和槽

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


Qt

  • **作者前言**
  • 打印hello world
  • QT的编码格式
  • 使用编辑框进行输出hello wrold
  • 点击按钮
  • 信号和槽
    • 信号
    • 使用
    • 自定义信号
    • 自定义槽
    • 带参数的信号和槽
  • 窗口坐标体系
  • Q_OBJECT的介绍
  • 信号和槽的连接方式
  • 信号和槽 的断开
  • 总结

打印hello world

第一种方法,
在ui文件里面进行编辑
在这里插入图片描述
输入内容,然后运行文件,可以打印出来

第二种方法可以写c++代码进行运行出来
这里需要包含QLabel头文件, 这个头文件是之前Qt用的头文件风格
就好比19989年的c++98规定统一使用#include代替#include<stdio.h>头文件
还需要注意的是: 在Qt中,有自己的一套轮子,
QString、 QVector、QList 这些是Qt代码中常见的类型,一一对应的就是C++的string 、vector、list等类型
在这里插入图片描述

 QLabel *labe = new QLabel(this);//推荐在堆上创建,给labe指定一个父节点labe->setText("Hello world");//

图中代码,调用了QLabel的方法,使其显示出来,setText的参数是一个Qstring
如图:
在这里插入图片描述
这个方法默认显示到左上角,
观察代码,可以发现没有释放空间,会造成内存泄漏,这是潜意识,
但是是不会内存泄漏的,因为是把这个对象挂到了对象树上了
在这里插入图片描述
使用对象树,把内容组织起来,在合适的时候统一释放(窗口关闭时),但是如果挂在树上的对象提前销毁了,就会导致对应的的控件在界面上不存在了
如图:
在这里插入图片描述
所以说,labe对象会随对象树释放
我们也可以写一个类来进行观察,继承这个QLabel这个内置类,
在这里插入图片描述
.h

#include<QLabel>class mylabel : public QLabel
{
public:mylabel(QWidget* parent);~mylabel();};

.cpp

#include<QDebug>
mylabel::mylabel(QWidget* parent):QLabel(parent)
{}mylabel::~mylabel()
{qDebug()<< "释放了";//字符的编码格式和这个文件的编码格式一样//终端的编码格式不一样//
}

在构造函数中,必须指定父类,这样才能挂在对象树上,否则的话,只能自己手动的进行delete了

回归到原来问题上去,

QT的编码格式

在qt中,我们使用std::cout打印输出就会出现编码格式错误,
例如:

在这里插入图片描述

所以qt有自己的处理工具,或是使用Qstring类型
我们需要包含头文件<QDebug>,使用qDebug()来打印输出,

在这里插入图片描述qDebug()是一个宏,里面封装了一个QDebug对象,所以使用qDebug()相当于std::cout
需要注意是windos不要使用cout, 但是Linux可以,因为Linux的编码格式是utf-8,cpp的文件的编码格式也是utf-8

使用编辑框进行输出hello wrold

上面在程序面板中简单 输出了hello wrold, 这次我们来试试编辑框 QLineEdit,在设计中也可以通过ui文件进行设计,

bfd897d17.png)

在这里插入图片描述
接下来我们使用c++的纯代码来进行实现
还是一样的道理,使用啥控件就导入对应控件的名字(头文件), 导入#include<QLineEdit>
如图:

在这里插入图片描述
代码的写法还是一样的, 控件对象初始化一定要指明父类(父节点),

点击按钮

除了上面的方法,我们也可以通过点击按钮在程序面板中输出
这里需要我们导入头文件#include<QPushButton>

QPushButton * qbutton = new QPushButton(this);
qbutton->setText("hell world");

如图:
在这里插入图片描述

这个按钮点击是没有效果的,需要建立一个点击操作,这就涉及到信号和槽了

信号和槽

在Qt中,⽤户和控件的每次交互过程称为⼀个事件。⽐如"⽤⼾点击按钮"是⼀个事件,"⽤户关闭窗⼝"也是⼀个事件。每个事件都会发出⼀个信号,例如⽤⼾点击按钮会发出"按钮被点击"的信号,⽤⼾关闭窗⼝会发出"窗口被关闭"的信号,而在Qt中,对信号做出的响应动作就称之为槽

注意:信号的本质就是事件

槽的本质
槽(Slot)就是对信号响应的函数。槽就是⼀个函数,与⼀般的C++函数是⼀样的,可以定义在类的任何位置(public、protected或private),可以具有任何参数,可以被重载,也可以被直接调⽤(但是不能有默认参数)。槽函数与⼀般的函数不同的是:槽函数可以与⼀个信号关联,当信号被发射时,关联的槽函数被⾃动执⾏

说明
(1)信号和槽机制底层是通过函数间的相互调⽤实现的。每个信号都可以⽤函数来表⽰,称为信号函数;每个槽也可以⽤函数表⽰,称为槽函数。例如:"按钮被按下"这个信号可以⽤clicked()函数表⽰,"窗⼝关闭"这个槽可以⽤close()函数表⽰,假如使⽤信号和槽机制实现:"点击按钮会关闭窗⼝"的功能,其实就是clicked()函数调⽤close()函数的效果。
(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:
• 信号函数⽤ signals关键字修饰,槽函数⽤public slots、protected slots或者private slots修饰。signals和slots是Qt在C++的基础上扩展的关键字,专⻔⽤来指明信号函数和槽函数;
• 信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)

信号

在Linux中,进程的通讯方式是信号, signal,
谁发出来的,啥类型的信号, 怎么处理,
而在Qt中也有自己的信号,
涉及到三个要素
简单的理解的就是, 信号源、 信号类型, 处理方式(槽, connect的使用)

使用

在Qt中Qobject类中提供一个静态函数connet(),该函数专⻔⽤来关联指定的信号函数和槽函数
connect() 函数原型:

bool QObject::connect(const QObject *sender, 
const char *signal, 
const QObject *receiver,const char *method, Qt::ConnectionType type = Qt::AutoConnection);

sender:信号的发送者;

signal:发送的信号(信号函数);传入函数指针

receiver:信号的接收者;

method:接收信号的槽函数;传入函数指针
type
= Qt::AutoConnection )

type:⽤于指定关联⽅式,默认的关联⽅式为Qt::AutoConnection,通常不需要⼿动设定。
在这里插入图片描述
这写了两个,从图中可以看出,qbutton是new出来的, pushButton是ui文件通过qmake生成的,
这个变量名我们是可以控制的,如果要更改的话,
如图:

在这里插入图片描述
qmake会根据ui文件的objectName对应的值,生成的变量名(唯一),我们也可以更改这个值,
我们这个值修改为puBu
如图:
在这里插入图片描述

需要注意的是:&QPushButton::clicked 是函数指针,
代码:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget),qbutton(new QPushButton(this))
{ui->setupUi(this);/*QLineEdit* qlineedit = new QLineEdit(this);qlineedit->setText("hello world");*/ // 单编辑框qbutton->setText("hell world");connect(qbutton,&QPushButton::clicked,this, &Widget::funtion);connect(ui->puBu,&QPushButton::clicked,this, &Widget::funtion);
}
void Widget:: funtion()
{qDebug() << "点击成功";if(ui->puBu->text()==QString("点击")){ui->puBu->setText("成功点击");}else{ui->puBu->setText("点击");}}

.h

class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void funtion();
private:Ui::Widget *ui;QPushButton * qbutton;
};

看到这里, 很多人会迷惑,为啥在qt中,会使用不同的类型的指针进行传参,在c++中不能这样做的,
这是因为在以前的Qt版本中, connect传参需要传入宏的, 分别是SIGNAL和SLOT,
写法如下:

connect(btn, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close));

这两个宏的作用就是把函数指针类型转换成char*
而在QT5之后,就增加了泛型编程,也就是函数模板,
在这里插入图片描述

自定义信号

信号本质就是事件, 也就是一个“函数”,但是信号是一个特殊的函数, 程序员只要声明这个函数就行,至于函数的定义,是qt在编译的过程自动生成的(生成过程,程序员无法干预)

需要注意的是: 信号函数的返回值必须是void, 也没有形参都可以,重载函数也可以
在qt中有关键字signals:这个是c++没有的
至于怎么定义的函数, 是qmake在调用一些工具的时候,扫描到signal的时候,就会根据函数声明写出一个函数定义,
下面我们先声明一个信号函数,然后使用connect把信号和槽建立连接
在这里插入图片描述
然后我们运行起来, 就会发现。我们该怎么触发信号, 前面我们使用内置的点击可以触发信号,但是现在我们自定义信号, 没有这样的功能 这里Qt就引入了emit关键字, 使用这个关键字触发我们声明的信号函数

emit this->myclicked();

如图:
在这里插入图片描述
在Qt5中不写这个emit也可以

自定义槽

顾名思义,简单的理解就是一个函数的声明加定义,所以说当我们要定义一个槽函数需要按照Qt的写法进行,
槽函数写法1
在Qt中有c++中没有的关键字,为了区分普通函数和槽函数,qt增加了如下关键字

public slots:
protected slots;
private slots

槽函数定义和声明在其中,这样可以一目了样,就算不写在其中,也是可以的,这个要看程序员怎么写
槽函数写法2
除了上面的纯代码方式,还可以在ui文件进行
如图:

点击进行就会看到如下:
在这里插入图片描述
然后选择好信号就会生成对应的槽函数
在这里插入图片描述
然后我们只需要函数里面写我们的内容就行,
当我们运行的时候就会发现, qt文件中没有使用connect,而生成的ui_widget.h的头文件也没有,
这是因为,在QT中,信号和槽的链接不局限于使用connect, 还可以通过函数名的方式来链接
而生成的函数名字也是有讲究的,如图:
在这里插入图片描述
我们知道QPushButton有clicked这个函数,如果我们当名字更改了就会报错,
当我们更改后,
在这里插入图片描述

就会发现,输出的那里有一个函数名字叫做connectSlotsByName,这个对应着头文件ui_widget.h
在这里插入图片描述
当调用这个函数的时候,就会调用对应的函数名链接的规则,进行信号和槽的链接, 如果这个函数(connectSlotsByName)没有调用, 哪怕在Qt文件中没有更改函数名,也会报错,

总结:
如果我们时使用图形化工具创建控件的话,就使用函数名链接规则进行信号和槽的连接,
如果是纯代码的方式来创建控件的话,要使用connect来,因为我们没有调用connectSlotsByName这个函数

带参数的信号和槽

前面我们自定义或者内置的类的成员函数,都是没有参数的,如果要想写一个带有参数的信号函数,对应的槽函数也要带参数, 并且参数类型要一致,个数不一致也可以,信号函数参数个数 >= 槽函数参数个数
下面我写了一段代码

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);btn = new QPushButton("点击",this);connect(btn, &QPushButton::clicked, this,&Widget::HandBtn);connect(this, &Widget::myclicked, this, &Widget::handmyclicked);}Widget::~Widget()
{delete ui;
}void Widget::handmyclicked(const QString& ch)
{this->setWindowTitle(ch);
}void Widget::HandBtn()
{btn->move(200,300);emit this->myclicked("无敌大厂");
}

大致思路:
在这里插入图片描述

窗口坐标体系

前面我们使用代码写出来的,都是默认在程序面板的左上角显示的,而在qt中的
坐标体系:以左上⻆为原点(0,0),X向右增加,Y向下增加。
在这里插入图片描述
在qt中,给某个控件设置位置的时候,相对于的坐标原点,就是父窗口的左上角
在这里插入图片描述
前面我们简单的理解了对象树, QPushButton作为Qwidget的子节点,对应的坐标原点就是QWidget框的左上角
当我们运行起来就会默认在qwidget的左上角,
在这里插入图片描述
我们可以使用move函数

void move(int x, int y);

就会在(x,y)处开始显示,这个是相对于Qwidget这个父框的
如图:
在这里插入图片描述

我们也可以给Qwidget这个窗口进行设置,

Q_OBJECT的介绍

前面我们知道,如果一个类中要定义和使用信号和槽(或者定义和声明信号和槽),就需要类开始的地方写入宏 Q_OBJECT,否则就会报错

信号和槽的连接方式

在大部分的GUI网页开发中,主要形式不是使用connect这样的形式,(一对一形式)

funtion handle()
{
.....
}
button.onclick = handle;

只要点击就会触发函数, 这种方式有很多, 但是在Qt中, 搞出connect这样的方式,是为了解决信号和槽的耦合, 也就是实现处理 用户的操作控件和处理用户的操作的逻辑,(一个控件需要产生不同的效果),也叫解耦合
还有就是实现一个信号连接多个槽函数,或者一个槽函数连接多个信号,
总结: 在qt中信号和槽的连接有一对一. 一对多以及多对多的方式

信号和槽 的断开

关键字: disconnect
代码如下:


Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot1);connect(ui->pushButton2, &QPushButton::clicked, this, &Widget::Myslot2);
}Widget::~Widget()
{delete ui;
}void Widget::Myslot1()
{qDebug()<< "Myslot1";this->setWindowTitle("东东");
}
void Widget::Myslot2()
{qDebug()<< "Myslot2";//断开disconnect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot1);//重新连接connect(ui->pushButton1, &QPushButton::clicked, this, &Widget::Myslot3);
}
void Widget::Myslot3()
{qDebug()<< "Myslot3";this->setWindowTitle("喜喜");
}

如图:
在这里插入图片描述
disconnect一般不怎么使用,主动断开连接,一般情况下是连接其他的槽函数,
除了上面这样声明和定义槽函数, 还可以使用lambda表达式
在这里插入图片描述
但是需要注意到是Qt中的lambda表达式支持是在c++11的基础上的,Qt5之后的版本,如果是Qt5之前的版本,就需要在.pro文件中更改一下,如图:
在这里插入图片描述

总结

Linux中的信号和Qt中的信号有很多相似点,

  1. 信号源
    2)信号类型
    3)信号的处理方式

信号和槽的连接和使用
connect的使用和disconnect的使用

自定义信号和槽函数
Q_OBJECT宏
lambda表达式

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

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

相关文章

C#笔记4 详细解释事件及其原型、匿名方法和委托的关系

匿名方法 定义 匿名方法允许一个与委托关联的代码被内联的写入使用委托的位置。 语法形式 delegate(参数列表) {代码块 } 前文说过&#xff0c;委托是定义了一个公司&#xff0c;公司专门承接某一类型的任务。 委托的实例化就是公司把任务交给了具体的职员&#xff08;方…

掌握测试的艺术:深入探索Python的pytest库

文章目录 **掌握测试的艺术&#xff1a;深入探索Python的pytest库**背景&#xff1a;为什么选择pytest&#xff1f;pytest是什么&#xff1f;如何安装pytest&#xff1f;5个简单的库函数使用方法1. pytest.main()2. pytest.skip()3. pytest.mark.parametrize()4. pytest.raises…

基于物联网的低成本便携式传感器节点用于火灾和空气污染的检测与报警

目录 摘要 引言 材料和方法 传感器节点 IoT 微控制器 颗粒物传感器 环境和气体传感器 MQTT代理 Node-Red监控平台 系统结构 数据存储 工作描述 实验结果 讨论 结论 致谢 参考文献 这篇论文的标题是《Low-cost IoT-based Portable Sensor Node for Fire and Air…

STM32G474之TIM1捕获1模式

STM32G474采用TIM8产生方波信号&#xff0c;使用TIM1工作于捕获1模式&#xff0c;并计算方波频率。捕获方波周期&#xff0c;在有些开发中&#xff0c;还是能用到。建议开发时使用HAL库自带的库函数。使用寄存器方法也可以实现&#xff0c;但是后期修改不太方便。 测试时&…

利用 Web 浏览器构建 Java Media Player

如果您需要在 Java 桌面应用程序中嵌入媒体播放器&#xff0c;有几种方法可供选择&#xff1a; 您可以使用 JavaFX Media API 来实现所有必需的媒体播放器功能。虽然稍显过时但仍然可用的 Java Media Framework 也可以作为一种解决方案。您可以集成像 VLCJ 这样的第三方 Java …

如何选择适合企业的财税自动化解决方案

财税自动化解决方案是现代企业提升财务管理效率、降低运营成本的关键工具。然而&#xff0c;市场上的财税自动化产品琳琅满目&#xff0c;功能各异&#xff0c;企业在选择时常常感到困惑。本文金智维将从中小型的需求出发&#xff0c;帮助企业了解如何选择适合自身的财税自动化…

QT实战项目之音乐播放器

项目效果演示 myMusicShow 项目概述 在本QT音乐播放器实战项目中,开发环境使用的是QT Creator5.14版本。该项目实现了音乐播放器的基本功能,例如开始播放、停止播放、下一首播放、上一首播放、调节音量、调节倍速、设置音乐播放模式等。同时还具备搜索功能,通过搜索歌曲名字…

另一种关于类的小例

前言 我们还是以一段关于构造函数的代码作为开端&#xff0c;我们以之前银行家的小项目为背景 class Account {constructor(owner, currency, pin) {this.owner owner;this.currency currency;this.pin pin;} }const ITshare new Account(ITshare, EUR, 21211); console.…

零基础入门天池镜像提交--windows场景VirtualBox虚拟机安装linux系统并ssh远程登录,直至镜像的制作及提交

背景&#xff1a;由于本人只有一台windows,天池上的比赛需要提交镜像&#xff0c;自己试了好多方法给windows安装linux&#xff0c;但是始终没安装成功。最终采用在利用VirtualBox安装linux虚拟机&#xff0c;使用MobaXterm进行ssh登陆linux&#xff0c;镜像的制作、push、提交…

Java+Swing实现学生选课管理系统

JavaSwing实现学生选课管理系统 一、系统介绍二、系统展示1.课程查询2.课程添加3.退课 三、系统实现四、其他1.其它系统2.获取源码 一、系统介绍 本系统实现了学生登录和管理员登录&#xff0c;学生实现选课&#xff0c;查看已选课程&#xff0c;修改密码&#xff0c;查看学生…

Java | Leetcode Java题解之第386题字典序排数

题目&#xff1a; 题解&#xff1a; class Solution {public List<Integer> lexicalOrder(int n) {List<Integer> ret new ArrayList<Integer>();int number 1;for (int i 0; i < n; i) {ret.add(number);if (number * 10 < n) {number * 10;} els…

顺序表

目录 1. 数据结构 2. 顺序表 1&#xff09;线性表 2&#xff09;顺序表分类 3、动态顺序表的实现 1. 数据结构 数据&#xff1a;常见的数值1、2、3、4.....、教务系统里保存的用户信息&#xff08;姓名、性别、年龄、学历等 等&#xff09;、网页里肉眼可以看到的信息&…

vTESTstudio系列12--vTESTstudio中的动态函数库介绍2

在上期的文章&#xff08;vTESTstudio系列11--vTESTstudio中的动态函数库介绍1&#xff09;中&#xff0c;我们详细介绍了osek_tp.dll的接口&#xff0c;本章开始给大家介绍如何通过osek_tp.dll的接口去发送诊断指令&#xff0c;Let‘s Go!!! 目录 1. CanTp发送数据的函数&am…

图表操作——图表保存为图片+多个图表批量保存为压缩包——js技能提升

使用场景&#xff1a; echarts图表&#xff1a;生成的柱状图/折线图/饼图等可以实现图表的导出&#xff0c;导出格式为一个图片。也可以支持多个图表同时导出为图片&#xff0c;以压缩包的形式下载下来。 下面介绍单个导出批量导出的具体用法&#xff1a; 1.单个导出功能——…

可信捐赠系统的设计与开发论文

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统可信捐赠系统信息管理难度大&#xff0c;容错率低&#x…

选对文档版本管理软件:10款工具详解

本篇文章中提到的工具包括&#xff1a;1.PingCode&#xff1b;2.Worktile&#xff1b;3.联想Filez&#xff1b;4.蓝凌云&#xff1b;5.阿里云盘&#xff1b;6.360亿方云&#xff1b;7.无忧企业文档&#xff1b;8.DocStar ECM&#xff1b;9.Dropbox Business&#xff1b;10.Shar…

数据库之心:MySQL 探索(一)mysql的安装和基本介绍

欢迎来到我们的MySQL博客&#xff01;在这里&#xff0c;我们将深入探讨MySQL数据库系统的各个方面&#xff0c;包括基础知识、优化技巧、实践案例以及最新的行业趋势。 目录 前言 什么是数据库&#xff1f; 数据库产品 MySQL安装 解压 配置 添加环境变量 初始化MySQL …

Linux云计算 |【第二阶段】SHELL-DAY4

主要内容&#xff1a; grep、egrep的使用&#xff0c;基本/扩展正则、sed的使用&#xff08;非交互、逐行处理、常用命令与选项&#xff09; 补充&#xff1a;grep [-E]选项&#xff0c;表示允许使用扩展的正则表达式&#xff08;同等于egrep&#xff09; 一、grep 与 egrep 的…

基于深度学习的单目标跟踪系统

基于深度学习的单目标跟踪&#xff0c;效果吊打传统算法&#xff0c;3060显卡上达到实时&#xff0c;代码python和c两个版本都有。 基于深度学习的单目标跟踪系统是一种先进的计算机视觉技术&#xff0c;它可以实现实时的、高精度的目标跟踪。与传统的基于特征匹配或模板匹配的…

LED的使用寿命评估

一&#xff0e;前言 LED光源随着时间的推移&#xff0c;输出光功率会逐渐衰减。在某一时间点&#xff0c;当LED发出的光衰减到一定水平&#xff0c;就无法满足应用要求。因此&#xff0c;常遇见客户会索取产品中LED光源的使用寿命数据。那么怎样确认LED的使用寿命呢&#xff1…