嵌入式QT (Qt 信号与槽)

news2024/9/21 9:51:48

一、Qt 信号与槽机制

因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。

信号(Signal)就是在特定情况下被发射的事件。
GUI 程序设计的主要内容就是对界面上各组件的信号的响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。
(Slot)就是对信号响应的函数。槽就是一个函数,与一般的 C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:

connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

sender 是发射信号的对象的名称,signal() 是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数。receiver 是接收信号的对象名称,slot() 是槽函数的名称,需要带括号,有参数时还需要指明参数。

关于信号与槽的使用,有以下一些规则需要注意:
一个信号可以连接多个槽,例如:

connect(pushButton, SIGNAL(clicked()), this, SLOT(hide());
connect(pushButton, SIGNAL(clicked()), this, SLOT(close());

这是当一个对象 pushButton 的被单击时,所在窗体有两个槽进行响应,一个 hide()用于隐藏主窗体,一个 close 用于关闭主窗体。

多个信号可以连接同一个槽,如下:

connect(pushButton,SIGNAL(clicked()),this,SLOT(close()));
connect(pushButton_2,SIGNAL(clicked()),this,SLOT(close()));
connect(pushButton_3,SIGNAL(clicked()),this,SLOT(close()));

这样,当任何一个 pushButton 被单击时,都会执行 close()函数,进而关闭或者退出程序。

一个信号可以连接另外一个信号(说明了 connect 万物皆可连,非常好用!),例如:

connect(pushButton, SIGNAL(objectNameChanged(QString)),this, SIGNAL(windowTitelChanged(QString)));

这样,当一个信号发射时,也会发射另外一个信号,实现某些特殊的功能。

在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT(特别重要)。

当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。

总结如下图,可以看到发送者与发送的信号是在一起的,接收者与接收的信号/槽是在一起的。它们不能在 connect()方法里写乱顺序!由发送者发送出信号到接收者用信号/槽接收。
在这里插入图片描述
disconnect(),这个方法重载了好几个函数,解开格式如
下。

bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)

1、断开一切与 myObject 连接的信号或槽。

disconnect(myObject, 0, 0, 0);

相当于非静态重载函数:

myObject->disconnect();

2、断开所有连接到特定信号的东西。

disconnect(myObject, SIGNAL(mySignal()), 0, 0);

相当于非静态重载函数:

myObject->disconnect(SIGNAL(mySignal()));

3、与指定的接收者断开连接。

disconnect(myObject, 0, myReceiver, 0);

相当于非静态重载函数:

myObject->disconnect(myReceiver);

二、 如何在项目里创建信号

由于信号只需声明,无需定义。所以我们只需要在 mianwindow.h 里声明信号即可。代码如下,如下图黑色加粗部分代码就是创建的信号。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
/* 引入 QPushButton */
#include <QPushButton>

class MainWindow : public QMainWindow
{
	Q_OBJECT
	
public:
	MainWindow(QWidget *parent = nullptr);
	~MainWindow();
	
signals:
	/* 声明一个信号,只需声明,无需定义 */
	void pushButtonTextChanged();

};
#endif // MAINWINDOW_H

三、如何在项目中创建槽

创建槽的方法也很简单,也是直接在 mianwindow.h 里直接声明槽,在 mianwindow.cpp 里实现槽的定义,声明槽必须写槽的定义(定义指函数体的实现),否则编译器编译时将会报错。

槽有以下特点:

  1. 槽可以是任何成员函数、普通全局函数、静态函数
  2. 槽函数和信号的参数和返回值要一致

根据上面的槽特点,由于我们在第二小节里声明了信号void pushButtonTextChanged();所以我们声明的槽函数必须是无返回值类型void,和无需参数。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
/* 引入 QPushButton */
#include <QPushButton>

class MainWindow : public QMainWindow
{
	Q_OBJECT
	
public:
	MainWindow(QWidget *parent = nullptr);
	~MainWindow();
	
	
signals:
	/* 声明一个信号,只需声明,无需定义 */
	void pushButtonTextChanged();
	
public slots:
	/* 声明一个槽函数 */
	void changeButtonText();
	
	/* 声明按钮点击的槽函数 */
	void pushButtonClicked();
	
private:
	/* 声明一个对象 pushButton */
	QPushButton *pushButton;
};
#endif // MAINWINDOW_H

在 mainwindow.cpp 里实现 声 明 的 槽 函 数 void changeButtonText();voidpushButtonClicked();。同时还实例化了 pushButton 对象。代码如下。

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
	/* 设置窗体的宽为 800,高为 480 */
	this->resize(800,480);
	
	/* 实例化 pushButton 对象 */
	pushButton = new QPushButton(this);
	
	/* 调用 setText()方法设定按钮的文本 */
	pushButton->setText("我是一个按钮");
}

MainWindow::~MainWindow()
{

}

/* 实现按钮点击槽函数 */
void MainWindow::pushButtonClicked()
{
	/* 使用 emit 发送信号 */
	emit pushButtonTextChanged();
}

/* 实现按钮文本改变的槽函数 */
void MainWindow::changeButtonText()
{
	/* 在槽函数里改变按钮的文本 */
	pushButton->setText("被点击了!");
}

四、 如何在项目中连接信号与槽

信号槽连接的代码如下。

connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));
connect(this, SIGNAL(pushButtonTextChanged()), this, SLOT(changeButtonText()));

注意,发送信号的对象,和接收的信号的对象。因为我们 pushButtonClicked()是本类里定义的槽,所以用 this 来接收。同理,pushButtonTextChanged()也是本类定义的信号。所以发送者写成 this。changeButtonText()也是本类的槽函数,所以接收槽的对象也是 this。

在 mainwindow.cpp 中信号槽连接的代码如下。

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
 : QMainWindow(parent)
{
	/* 设置窗体的宽为 800,高为 480 */
	this->resize(800,480);
	
	/* 实例化 pushButton 对象 */
	pushButton = new QPushButton(this);
	
	/* 调用 setText()方法设定按钮的文本 */
	pushButton->setText("我是一个按钮");
	
	/* 信号与槽连接 */
	connect(pushButton, SIGNAL(clicked()), this,SLOT(pushButtonClicked()));
	
	connect(this, SIGNAL(pushButtonTextChanged()), this,SLOT(changeButtonText()));
}

MainWindow::~MainWindow()
{

}

/* 实现按钮点击槽函数 */
void MainWindow::pushButtonClicked()
{
	/* 使用 emit 发送信号 */
	emit pushButtonTextChanged();
}

/* 实现按钮文本改变的槽函数 */
void MainWindow::changeButtonText()
{
	/* 在槽函数里改变按钮的文本 */
	pushButton->setText("被点击了!");
}

整个流程就是当点击了按钮,然后触发了 pushButtonClicked()pushButtonClicked()槽里发送 pushButtonTextChanged()信号,changeButtonText()槽响应 pushButtonTextChanged()信号,我们在 changeButtonText()槽实现响应的动作(事件)。最终的实现效果是按钮的文本由“我是一个按钮”被点击时变成“被点击了!”。

五、学会使用 Qt 类的信号与槽

要想使用 Qt 的信号与槽,那么我们必须知道有哪些信号与槽。在 第四节的代码里。

connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));

如下图示,按住 Ctrl 键,再点击 clicked(),进入 clicked()这个信号的定义处。
在这里插入图片描述
进入 QPushButton 的定义处,我们看到 QPushButton 不止 clicked 信号,还有其他信号,也有 QPushButton 的槽函数(返回上一步按 Alt + 方向左键)。在这里我们只是简单的看了如何在已知信号和槽里查找其他信号与槽。实际上在开发中我们经常需要使用 Qt 帮助文档来查看 Qt定义的信号与槽。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL_第05章_排序与分页

第05章_排序与分页 讲师&#xff1a;尚硅谷 - 宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a; http://www.atguigu.com 1. 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;: 升序 DESC&#xff08;desc…

物流管理APP软件开发公司 让货运变得更简单

随着互联网技术的发展&#xff0c;人们的生活方式也发生了很大的变化&#xff0c;移动互联网如今已经深入到生活的方方面面&#xff0c;就连物流运输行业也开始涌现出各种货运物流管理APP软件&#xff0c;让整个物流管理过程更加简单。下面我们一起来看一下为什么越来越多的运输…

数据库实验 | 第4关:修改多个数据表的存储过程

任务描述 本关任务&#xff1a; 图书管理数据库有读者reader图书book借阅数据表 读者表reader有读者证号dzzh、姓名xm、性别xb、身份sf、电话号码dhhm字段 图书表book有条形码txm、书名sm、分类号flh,作者zz,出版社cbs,出版日期cbrq,售价sj,典藏类别dclb,在库zk,币种bz字段 …

【DEBUG】错误手册集

文章目录 1.sshd启动报错,无法绑定端口2.克隆后的虚拟机可以联网&#xff0c;但是Xshell连接失败的解决办法 1.sshd启动报错,无法绑定端口 (1) 首先排查是否有端口占用&#xff08;没有发现问题&#xff09; netstat -ano | grep sshd(2) 查看 message 日志存在如下错误信息&…

MySQL数据库,联合查询

目录 1. 联合查询 1.1 内查询 1.2 外查询 1.3 自连接 1.4 子查询 1.5 合并查询 1. 联合查询 联合查询&#xff0c;简单的来讲就是多个表联合起来进行查询。这样的查询在我们实际的开发中会用到很多&#xff0c;因此会用笛卡尔积的概念。 啥是笛卡尔积&#xff1f;两张表…

深度学习 -- 张量操作与线性回归 张量的数学运算以及用张量构建线性回归模型

前言 这篇博客继承前篇博客的内容&#xff0c;将对张量的操作进行阐述&#xff0c;同时在理解张量的一些数学的基础上&#xff0c;配合机器学习的理论&#xff0c;在pytorch环境中进行一元线性回归模型的构建。 张量的拼接与切分 torch.cat() 功能&#xff1a;将张量按维度d…

Node.js四:包管理工具

1.介绍 2.npm安装 3.npm基本使用 属性翻译 4.搜索下载安装包 npm搜索网站&#xff1a; npm 5.生产环境与开发环境 开发环境 是程序员 专门用来写代码 的环境&#xff0c;一般是指程序员的电脑&#xff0c;开发环境的项目一般 只能程序员自己访问 生产环境 是项目 代码正式运行 …

海光信息业绩高歌猛进,但其作为国产CPU龙头的“地基”并不牢固

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 在“芯片寒冬”的大背景下&#xff0c;2022年全球头部芯片半导体公司纷纷下调业绩预期&#xff0c;英特尔、英伟达、美光等无一幸免。但是随着AIGC异军突起&#xff0c;仿佛寒冬中的一股暖流&#xff0c;催生着半导体市场行…

第四章 面向对象(OOP)

目录 一、编程思想 1.1. 面向对象 1.2. 面向过程 1.3.举例说明&#xff08;把大象装进冰箱&#xff09; 1.4.二者的联系与区别 1.5.面向对象的三个阶段 1.6.什么是类&#xff0c;什么是实例&#xff0c;二者的联系 二、面向对象三大特征 2.1 封装 2.2 继承 2.3 多态…

go-zero入门

文章目录 简介框架设计环境准备go安装Go Module设置goctl安装安装(mac\&linux)安装(windows) protoc & protoc-gen-go安装 goctl 各层代码生成一览goctl 生成REST和RPC微服务生成数据模型层Model生成API服务目录结构开发者需要做的修改配置文件修改上下文依赖修改业务逻…

CMake基本使用

重要指令 cmake_minimum_required:指定CMake最小版本要求 project&#xff1a;定义工程名称&#xff0c;并可指定语言 set&#xff1a;显示的定义变量 include_directories&#xff1a;向工程添加多个特定头文件搜素路径 link_directories&#xff1a;向工程添加多个特定库文件…

Spring lettuce读写分离

Redis 的 Sentinel 模式默认配置下 Redis 的客户端只对 Master 读写&#xff0c;另外2个Slave闲置。若主从节点在不同机房&#xff0c;在读取时会有跨机房的网络时延&#xff0c;并且比同机房访问更容易发生网络丢包。故在一些场景可以考虑将跨机房的服务节点设置为读写分离 Re…

计算机组成原理——第五章中央处理器(下)

梦里不知身是客&#xff0c;一晌贪欢 文章目录 5.6.1 指令流水线的基本概念5.6.2 指令流水线的影响因素和分类五段式指令流水线5.7.1 多处理器的基本概念5.7.2 硬件多线程的基本概念 5.6.1 指令流水线的基本概念 想要对指令的过程进行优化&#xff0c;一条指令的执行过程可以被…

世界新冠疫情数countrydata.csv 表,实战分析

一、环境要求 Hadoop hive spark hbase开发环境 开启hadoop&#xff1a;start-all.sh开启zookeeper&#xff1a;zkServer.sh start开启hive&#xff1a;nohup hive --service metastore &nohup hive --service hiveserver2 & 打开hive界面&#xff1a;beeline -u …

单列集合之Set集合以及各种实现类

Set集合 Set接口也是Collection单列结合的一个子接口&#xff0c;set集合中没有提供其他额外的方法&#xff0c;但是相比较Collection集合新增了其他的特性。所有实现了Set接口的类都可以叫做Set集合。 Coliection接口中的方法&#xff1a;Collection集合的方法 Set集合不允…

更全面的对比GPT4和Claude对MLIR的掌握能力

本文构造了20个MLIR基础概念的问题以及使用OneFlow IR转换为Tosa IR的5个代码段来评测GPT4和Claude对于MLIR的掌握能力&#xff0c;我的结论是对于基础概念的理解Claude整体上和GPT4持平&#xff0c;而在阅读相关代码片段时Claude表现出了比GPT4更强一点的理解能力。 0x0. 前言…

【Python】读取r语言数据+NMF算法(完整代码+详细注释)

目录 依赖库代码功能完整代码总结 欢迎关注 『Python』 系列&#xff0c;持续更新中 欢迎关注 『Python』 系列&#xff0c;持续更新中 算法部分源码是我的数模兄弟想要深入研究nmf算法方面的内容发给我让我跑的 参考自博文 https://blog.csdn.net/atease0001/article/details/…

计及光伏电站快速无功响应特性的分布式电源优化配置方法(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

JS的函数定义和参数

文章目录 一、JavaScript 函数定义二、JavaScript 函数参数总结 一、JavaScript 函数定义 JavaScript 使用关键字 function 定义函数。 函数可以通过声明定义&#xff0c;也可以是一个表达式。 函数声明 function functionName(parameters) {执行的代码 }函数声明后不会立即…

【C++内联函数】

目录 前言内联函数的概念内联函数的特性内联函数的总结 前言 假设有这样的一个场景&#xff0c;有一个代码量不足三行的函数被调用了一万次&#xff0c;现在让你做优化&#xff0c;你会怎么考虑优化&#xff1f; 我们都知道函数调用是有时间和空间开销的。程序在执行一个函数之…