Qt 信号和槽-核心知识点小结(11)

目录

小结表格索引

disconnect函数

lambda表达式

啥是耦合,啥是内聚


简介:这是Qt信号和槽的最后一篇文章,最主要的是总结该信号和槽的核心知识点。以及该核心知识点的文章索引(表格太长了,手机可能看不完整,动动小手往左边滑滑就能看到)这应该也只是学习Qt路上的一个小小分支,不过路虽远,行则将至,事虽难,做则必成。加油!各位看官好友

小结表格索引

核心知识点 文章索引
1.Qt通过控件按钮实现hello world(信号槽的机制用法) Qt 通过控件按钮实现hello world + 命名规范(7)
2.信号槽的使用,connect函数,信号槽是啥(信号源 信号的类型,信号的处理方式) Qt坐标系 + 信号和槽 + connect函数(8)
3.如何查阅文档 一个控件中内置了哪些信号,信号都是何时触发 一个控件中内置了哪些槽,槽都是什么作用 需要的信号槽,很可能得到这个类的父类或祖宗类去查询 Qt坐标系 + 信号和槽 + connect函数(8)
4.自定义槽函数,本质上就是自定义一个普通的成员函数 还可以让Qt Creator 自动生成(虽然没有显示用connect, 但是可以通过函数名字特定规则来完成自动连接) Qt 自定义槽 + 自定义信号(9)
5.自定义信号,信号的本质也是一个成员函数 函数的定义是Qt自动生成的,咱们只需要写函数声明即可 signals:放在该关键字中。emit:可以完成信号的发射 Qt 自定义槽 + 自定义信号(9)
6.信号和槽还可以带参数 发射信号的时候可以把参数传给对应的槽 信号的参数和槽的参数要一致(类型匹配, 信号的参数要多于槽的参数) Qt 信号和槽的补充(10)
7.信号和槽存在的意义(解耦合,多对多效果) Qt 信号和槽的补充(10)
8.disconnect函数使用方式 Qt 信号和槽-核心知识点小结点(11)
9.lambda表达式(简化槽函数的定义) Qt 信号和槽-核心知识点小结点(11)
10.啥是耦合,啥是内聚 Qt 信号和槽-核心知识点小结点(11)

disconnect函数

使用disconnect函数是用来断开信号和槽的连接,使用方式与connect连接信号和槽是非常类似的。disconnect函数用得比较少,在大部分情况下,把信号和槽连接上以后就不用管了,一般是用来主动断开信号和槽,即把信号重新绑定到另外一个槽函数上

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 连接按钮1的信号和槽
    connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleclick1);
}

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

void Widget::handleclick1()
{
    // 点击按钮1后,将窗口的标题改为修改窗口标题1
    this->setWindowTitle("修改窗口标题1");
    // 打印日志,方便断开信号后,观察这个槽函数有没有运行
    qDebug() << "handleclick1";
}

这里先看不断开信号和槽连接的代码,可以看到当点击按钮1后,触发信号并运行了槽函数,不仅修改了标题还打印出日志,这里要注意的是:这里的按钮是编辑图形化界面的方式创建的,不是纯代码去创建按钮对象

现在要断开按钮1信号和槽的连接,断开操作在按钮2中执行,那就得先connect按钮2的信号和槽。connect可不能放在按钮2的槽函数中进行连接,因为都没有connect,点击按钮2后发出信号,槽函数也无法执行

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 连接按钮1的信号和槽
    connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleclick1);
    // 绑定按钮2的信号和槽
    connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::handleclick2);
}

void Widget::handleclick2()
{
    // 点击按钮2后,要先将按钮1触发的信号与handleclick1槽函数给断开
    disconnect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleclick1);
    // 点击按钮2后,将窗口标题改为-修改窗口标题2,再打印日志观察
    this->setWindowTitle("修改窗口标题2");
    qDebug() << "handleclick2";
}

lambda表达式

定义槽函数的时候也是可以使用lambad表达式的(很多编程语言都支持的一种语法糖,本质上就是一个匿名函数,主要应用在回调函数场景中,基本上是一次性使用)。下面是它最简单的用法

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* mybutton = new QPushButton(this);
    mybutton->setText("点击按钮改名");
    mybutton->move(200, 300);
    
    connect(mybutton, &QPushButton::clicked, this, [](){
        qDebug() << "lambda 被执行了";
    });
}

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

可当我想使用mybutton这个变量的时候,它说没有完全地捕捉到lambda中。这里也就牵扯到C++11中新增的ambda的相关语法知识,这是因为lambda表达式,它是一个回调函数,这个函数是无法直接获取到上层作用域中的变量的。那lambda为了解决上述问题,就引入了变量捕获的语法,通过变量捕获就能获取到外层作用域中的变量

cpp 复制代码
connect(mybutton, &QPushButton::clicked, this, [mybutton](){
    qDebug() << "lambda 被执行了";
    mybutton->move(300, 300);
    mybutton->setText("我是哈哈哈");
});

如果当前lambda里面想使用更多的外层变量咋办?那就用[=],这个写法的含义就是把上层作用域中所有变量名都给捕获进来

cpp 复制代码
connect(mybutton, &QPushButton::clicked, this, [=](){
    qDebug() << "lambda 被执行了";
    mybutton->move(300, 300);
    mybutton->setText("我是哈哈哈");
    this->move(200,300);
});

总结

  • 后续如果我们对应的槽函数比较简单而且是一次性使用的,就经常会写作这种 lambda的形式
  • 另外也要确认捕获到lambda内部的变量是有意义的,毕竟回调函数执行时机是不确定的(用户啥时候点击按钮不知道的),所以无论何时用户点击了按钮,捕获到的变量都能正确使用。QPushButton* mybutton = new QPushButton(this); 由于此处 mybutton 是 new 出来的变量,生命周期跟随整个窗口(挂到对象树上,窗口关闭才会释放)这个东西就可以在后面随时使用了
  • 类似的,this指向的对象,也就是 Widget w; 这个变量是在main函数结束销毁(main.cpp)main结束则说明进程结束了,只要进程不结束,widget 就可用,this 也就可用了
  • lambda 除了可以按照值的方式来捕获变量[=]还可以按照引用的方式来捕获[&](Qt中很少这么写)捕获到的变量一般就是各种控件的指针,指针变量按照值传递或者引用来传递,都无所谓。不过如果按引用,还得更关注这个引用的变量本身的生命周期,因为一旦这个变量生命周期结束就会造成空引用的问题
  • lambda 语法是C++11中引入的,对Qt5及其更高版本,默认就是按照C++11来编译的。如果使用Qt 4 或者更老的版本,就需要手动在.pro 文件中加上C++11的编译选项,CONFIG += c++11

啥是耦合,啥是内聚

耦合与内聚是计算机中非常常见的术语,平时写代码要追求 "高内聚,低耦合"

耦合

就拿生活中一个很常见的现象举个例子。在疫情的时候,咱们在学校上学,那有一天的时候,回到家发现咱自家老妈阳了,那心情非常的担忧与难受,也不想去上课,学习也学不进,就想得赶紧带老妈就去医院检查。这就是高耦合那在代码中,这一模块的代码会对另外一模块的代码运行有非常紧密的联系,一旦出现一点问题,两模块运行都会崩溃 。那有一天在视频上刷到网友阳了,就只能评论一句:加油,坚持住,那一天还是该干嘛就干嘛。这就是低耦合

内聚

也拿一个很常见的现象举个例子。以前的时候我用电脑,无论是下载文件,还是下载应用,也包括一些网页标签啊,都是随便下,随便放,随便收藏,这也就导致C盘直接炸了,要用的文件到处找不到,常用的网页标签经常要重复搜索。那这就是低内聚,写代码的时候,实现某个功能点,围绕这个功能的相关代码被放到整个项目的各个地方,那万一以后想要去修改相关代码那就是难如登天啊。那我将我的网页标签以不同的用途分别整理,以后要用到某个标签,只需要点开收藏夹就能用。那这就是高内聚,写代码的时候,某个功能点的代码都被集中放在一起了

总结

这里要特别注意:像Qt这样的框架,里面涉及到的很多机制都与编程语言(C++)/数据结构/操作系统/网络/数据库 的基础知识都是有相关关联的,Qt只是咱们路上的一道风景,它并不是我们学习的终点,不能只依托于Qt这一门技术,更应该全面发展(说物质点,只学Qt没有饭吃,很多面试Qt的也和上面的C++,数据结构,网络,系统息息相关)

相关推荐
逐雨~1 小时前
9.8C++作业
开发语言·c++
我爱挣钱我也要早睡!2 小时前
Java 复习笔记
java·开发语言·笔记
汇能感知7 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
疾风铸境7 小时前
qt+halcon开发相机拍照软件步骤
数码相机·qt·halcon·拍照
阿巴Jun7 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao8 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾8 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
抠脚学代码8 小时前
Ubuntu Qt x64平台搭建 arm64 编译套件
数据库·qt·ubuntu
利刃大大8 小时前
【高并发内存池】五、页缓存的设计
c++·缓存·项目·内存池
DKPT8 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习