Qt 信号和槽-核心知识点小结(11)
目录
小结表格索引
disconnect函数
lambda表达式
啥是耦合,啥是内聚
简介:这是Qt信号和槽的最后一篇文章,最主要的是总结该信号和槽的核心知识点。以及该核心知识点的文章索引(表格太长了,手机可能看不完整,动动小手往左边滑滑就能看到)这应该也只是学习Qt路上的一个小小分支,不过路虽远,行则将至,事虽难,做则必成。加油!各位看官好友
小结表格索引
核心知识点 | 文章索引 |
---|---|
1.Qt通过控件按钮实现hello world(信号槽的机制用法) | Qt 通过控件按钮实现hello world + 命名规范(7) |
2.信号槽的使用,connect函数,信号槽是啥(信号源 信号的类型,信号的处理方式) | Qt坐标系 + 信号和槽 + connect函数(8) |
3.如何查阅文档 一个控件中内置了哪些信号,信号都是何时触发 一个控件中内置了哪些槽,槽都是什么作用 需要的信号槽,很可能得到这个类的父类或祖宗类去查询 | |
4.自定义槽函数,本质上就是自定义一个普通的成员函数 还可以让Qt Creator 自动生成(虽然没有显示用connect, 但是可以通过函数名字特定规则来完成自动连接) | Qt 自定义槽 + 自定义信号(9) |
5.自定义信号,信号的本质也是一个成员函数 函数的定义是Qt自动生成的,咱们只需要写函数声明即可 signals:放在该关键字中。emit:可以完成信号的发射 | |
6.信号和槽还可以带参数 发射信号的时候可以把参数传给对应的槽 信号的参数和槽的参数要一致(类型匹配, 信号的参数要多于槽的参数) | Qt 信号和槽的补充(10) |
7.信号和槽存在的意义(解耦合,多对多效果) | |
8.disconnect函数使用方式 | Qt 信号和槽-核心知识点小结点(11) |
9.lambda表达式(简化槽函数的定义) | |
10.啥是耦合,啥是内聚 |
disconnect函数
使用disconnect函数是用来断开信号和槽的连接,使用方式与connect连接信号和槽是非常类似的。disconnect函数用得比较少,在大部分情况下,把信号和槽连接上以后就不用管了,一般是用来主动断开信号和槽,即把信号重新绑定到另外一个槽函数上
#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后,将窗口的标题改为修改窗口标题1this->setWindowTitle("修改窗口标题1");// 打印日志,方便断开信号后,观察这个槽函数有没有运行qDebug() << "handleclick1";
}
这里先看不断开信号和槽连接的代码,可以看到当点击按钮1后,触发信号并运行了槽函数,不仅修改了标题还打印出日志,这里要注意的是:这里的按钮是编辑图形化界面的方式创建的,不是纯代码去创建按钮对象
现在要断开按钮1信号和槽的连接,断开操作在按钮2中执行,那就得先connect按钮2的信号和槽。connect可不能放在按钮2的槽函数中进行连接,因为都没有connect,点击按钮2后发出信号,槽函数也无法执行
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表达式的(很多编程语言都支持的一种语法糖,本质上就是一个匿名函数,主要应用在回调函数场景中,基本上是一次性使用)。下面是它最简单的用法
#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为了解决上述问题,就引入了变量捕获的语法,通过变量捕获就能获取到外层作用域中的变量
connect(mybutton, &QPushButton::clicked, this, [mybutton](){qDebug() << "lambda 被执行了";mybutton->move(300, 300);mybutton->setText("我是哈哈哈");
});
如果当前lambda里面想使用更多的外层变量咋办?那就用[=],这个写法的含义就是把上层作用域中所有变量名都给捕获进来
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++,数据结构,网络,系统息息相关)