Qt_day3_信号槽
目录
信号槽
1. 概念
2. 函数原型
3. 连接方式
3.1 自带信号 → 自带槽
3.2 自带信号 → 自定义槽
3.3 自定义信号
4. 信号槽传参
5. 对应关系
5.1 一对多
5.2 多对一
信号槽
1. 概念
之前的程序界面只能看,不能交互,信号槽可以让界面进行人机交互。
信号槽是Qt在C++基础上新增的特性,类似于其他编程中的回调机制,其目的是实现对象之间的通信。
使用信号槽需要具备两个先决条件:
- 通信的对象必须继承自QObject
QObject是Qt所有对象的基类,内部规定了Qt最基础的对象特性。
- 类中要包含Q_OBJECT宏
2. 函数原型
信号槽的建立是通过connect函数实现的。
// 信号槽连接函数
// 参数1:发射者,因发起的对象n.
// 参数2:信号函数,因的动作v.,需要使用SIGNAL()包裹函数名称
// 参数3:接收者,果执行的对象n.
// 参数4:槽函数,果的动作v.,需要使用SLOT()包裹函数名称
QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char * slot) [static]
信号函数一定来自于发射者,槽函数一定来自于接收者。信号槽的连接必须在发射者对象和接收者对象创建完成后进行,如果成功连接后,发射者或接收者对象销毁了,连接断开。
信号槽的连接也可以程序员手动断开,只需要把connect函数改为disconnect即可,参数保持不变。
3. 连接方式
为了讲课,按照难易程度分为三种连接方式:
- 自带信号 → 自带槽
- 自带信号 → 自定义槽
- 自定义信号 → 槽
3.1 自带信号 → 自带槽
这种连接方式是最简单的连接方式,因为信号函数和槽函数都是Qt内置的,程序员只需要找到连接的四个参数,直接连接即可。
【例子】点击按钮,关闭窗口。
分析:
参数1:发射者——按钮对象
参数2:信号函数——点击
void QAbstractButton::clicked() [signals]
参数3:接收者——窗口对象
参数4:槽函数——关闭
bool QWidget::close() [slot]
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton *btn;
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(400,400);btn = new QPushButton("关闭",this);btn->move(100,100);// 参数1:发射者——按钮对象// 参数2:信号函数——点击// 参数3:接收者——窗口对象// 参数4:槽函数——关闭connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}Dialog::~Dialog()
{delete btn;
}
3.2 自带信号 → 自定义槽
这种连接方式是使用的最多的一种连接方式,因为在实际开发中,Qt无法预设所有的槽函数情况,对于复杂的操作执行逻辑,需要程序员手动编写槽函数。
槽函数是一种特殊的成员函数。
【例子】点击按钮,窗口向右下角移动10个像素,并且后台输出当前窗口的位置。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton *btn;// 槽函数的声明
private slots: // 最小权限原则void mySlot(); // 自定义槽函数
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(400,400);btn = new QPushButton("关闭",this);btn->move(100,100);// 连接信号槽connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}void Dialog::mySlot()
{// 先获得当前坐标int x = this->x();int y = this->y();// 移动move(x+10,y+10);// 输出当前窗口位置qDebug() << this->x() << this->y();
}Dialog::~Dialog()
{delete btn;
}
3.3 自定义信号
自定义信号通常用于解决一些对象之间“远距离”通信问题,本节属于强行使用,因此并不是问题最优解,只是为了展示自定义信号的使用方式。
【例子】点击按钮,按钮上显示点击的次数。
先忽略自定义信号,展示正常解法:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* btn;int count;private slots:void btnClickedSlot(); // 点击按钮的槽函数
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent),count(0) // 构造初始化列表
{resize(400,400);btn = new QPushButton("0",this);btn->move(200,200);connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
}void Dialog::btnClickedSlot()
{count++;// int → QStringQString text = QString::number(count);// 设置到按钮上显示btn->setText(text);
}Dialog::~Dialog()
{delete btn;
}
基于上面的解法,强行增加自定义信号发射环节:
信号函数是一种特殊的函数,只有声明没有定义,声明后可以直接配合emit关键字发射。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* btn;int count;signals:void countSignal(); // 自定义信号private slots:void btnClickedSlot(); // 点击按钮的槽函数void countSlot(); // 与自定义信号连接的槽函数
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent),count(0) // 构造初始化列表
{resize(400,400);btn = new QPushButton("0",this);btn->move(200,200);connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));connect(this,SIGNAL(countSignal()),this,SLOT(countSlot()));
}void Dialog::btnClickedSlot()
{count++;// 发射自定义信号emit countSignal();
}/*** @brief Dialog::countSlot* 中转之后更新按钮显示的槽函数*/
void Dialog::countSlot()
{QString text = QString::number(count);btn->setText(text);
}Dialog::~Dialog()
{delete btn;
}
4. 信号槽传参
信号槽可以进行参数传递,信号函数携带参数发射,槽函数可以收到此参数。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* btn;int count;signals:void countSignal(int); // 自定义信号private slots:void btnClickedSlot(); // 点击按钮的槽函数void countSlot(int); // 与自定义信号连接的槽函数
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent),count(0) // 构造初始化列表
{resize(400,400);btn = new QPushButton("0",this);btn->move(200,200);connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));connect(this,SIGNAL(countSignal(int)),this,SLOT(countSlot(int)));
}void Dialog::btnClickedSlot()
{count++;// 发射自定义信号(携带参数)emit countSignal(count);
}/*** @brief Dialog::countSlot* count参数是信号函数发来的,不是成员变量* 中转之后更新按钮显示的槽函数*/
void Dialog::countSlot(int count)
{QString text = QString::number(count);btn->setText(text);
}Dialog::~Dialog()
{delete btn;
}
需要注意的是:
- 理论上可以传递任意多个参数
- 信号函数的参数个数必须大于等于槽函数的参数个数
- 参数类型需要匹配
5. 对应关系
同一个信号可以连接到多个槽(一对多),多个信号也可以连接到同一个槽(多对一)。
5.1 一对多
槽函数也是成员函数,因此在一对多的连接关系中,把连接的多个槽函数可以看做是普通的成员函数,合并为一个槽函数。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* btn1;QPushButton* btn2;private slots:void btnClickedSlot1();void btnClickedSlot2();void btnClickedSlot3(); // 3 = 1 + 2
};#endif // DIALOG_H
dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(400,400);btn1 = new QPushButton("一对多", this);btn1->move(200,100);btn2 = new QPushButton("一对一", this);btn2->move(100,200);// 一对多connect(btn1,SIGNAL(clicked()),this,SLOT(btnClickedSlot1()));connect(btn1,SIGNAL(clicked()),this,SLOT(btnClickedSlot2()));// 一对一connect(btn2,SIGNAL(clicked()),this,SLOT(btnClickedSlot3()));
}void Dialog::btnClickedSlot1()
{qDebug() << "A";
}void Dialog::btnClickedSlot2()
{qDebug() << "B";
}void Dialog::btnClickedSlot3()
{// 直接把Slot1和Slot2两个函数当做普通的成员函数,// 使用this指针调用btnClickedSlot1();btnClickedSlot2();
}Dialog::~Dialog()
{delete btn1;
}
5.2 多对一
多对一的连接方式下,槽函数无法区分信号来源,可以在槽函数中调用sender函数获取发射者对象,从而判断信号来源。
// 在槽函数中调用,返回发射者对象
QObject * QObject::sender() const
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QDebug>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* btn1;QPushButton* btn2;private slots:void btnsClickedSlot();
};#endif // DIALOG_H
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(400,400);btn1 = new QPushButton("A",this);btn2 = new QPushButton("B",this);btn1->move(150,100);btn2->move(150,200);// 多对一connect(btn1,SIGNAL(clicked()),this,SLOT(btnsClickedSlot()));connect(btn2,SIGNAL(clicked()),this,SLOT(btnsClickedSlot()));
}void Dialog::btnsClickedSlot()
{if(btn1 == sender()){qDebug() << "点击了按钮1";}else if(btn2 == sender()){qDebug() << "点击了按钮2";}qDebug() << "槽函数触发!";
}Dialog::~Dialog()
{delete btn1;delete btn2;
}
相关文章:

Qt_day3_信号槽
目录 信号槽 1. 概念 2. 函数原型 3. 连接方式 3.1 自带信号 → 自带槽 3.2 自带信号 → 自定义槽 3.3 自定义信号 4. 信号槽传参 5. 对应关系 5.1 一对多 5.2 多对一 信号槽 1. 概念 之前的程序界面只能看,不能交互,信号槽可以让界面进行人机…...
求从2开始的第n个素数
方法一:暴力法 思路:从2开始,逐个判断每个数是否为素数。素数是除了1和它自身外,不能被其他自然数整除的数。对于每个数m,从2到sqrt(m)遍历,如果能被整除则不是素数。当找到n个素数时停止。 C 代码如下&am…...

【Android】View—基础知识,滑动,弹性滑动
基础知识 什么是View 在 Android 中,View 是用户界面(UI)中的基本组件,用于绘制图形和处理用户交互。所有的 UI 组件(如按钮、文本框、图片等)都是 View 的子类。可以说,View 是构建 Android …...

MYSQL中的两种转义操作
在 MySQL 中,转义字符用于处理特殊字符,以防止语法错误或 SQL 注入攻击,而单双引号都是需要重点注意的字符 可以用转义符\ 和 两个连续的引号 来起到转义引号的作用 转义符转义: 这是users表中的数据 如果查询admin 或者 admin" 用户,可以用转义符\ 两个连…...

力扣题目解析--删除链表的倒数第n个节点
题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5]示例 2: 输入:head [1], n 1 输出:[]示例 3&…...

Knowledge Graph-Enhanced Large Language Models via Path Selection
研究背景 研究问题:这篇文章要解决的问题是大型语言模型(LLMs)在生成输出时存在的事实不准确性,即所谓的幻觉问题。尽管LLMs在各种实际应用中表现出色,但当遇到超出训练语料库范围的新知识时,它们通常会生…...
Android 项目模型配置管理
Android 项目配置管理 项目模型相关的配置管理config.gradle文件:build.gradle文件: 参考地址 项目模型相关的配置管理 以下是一个完整的build.gradle和config.gradle示例: config.gradle文件: ext {// 模型相关配置࿰…...

「QT」几何数据类 之 QSizeF 浮点型尺寸类
✨博客主页何曾参静谧的博客📌文章专栏「QT」QT5程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…...

Essential Cell Biology--Fifth Edition--Chapter one(2)
1.1.1.3 Living Cells Are Self-Replicating Collections of Catalysts 催化剂集合 生物最常被引用的特性之一是它们的繁殖能力。对于细胞来说,这个过程包括复制它们的遗传物质和其他成分,然后分裂成两个,产生一对子细胞[daughter cells]&a…...

大语言模型LLMs在医学领域的最新进展总结
我是娜姐 迪娜学姐 ,一个SCI医学期刊编辑,探索用AI工具提效论文写作和发表。 相比其他学科,医学AI,是发表学术成果最多的领域。 医学数据的多样性和复杂性(包括文本、图像、基因组数据等),使得…...
云防护单节点2T抗攻击能力意味着什么?
随着互联网的发展,DDoS攻击的规模和频率不断增加,对企业和个人用户的网络服务造成了严重威胁。云防护服务作为一种高效的DDoS防护手段,逐渐成为许多企业的首选。本文将重点讨论云防护单节点2T(太比特每秒)抗攻击能力的…...

IDEA在编译时: java: 找不到符号符号: 变量 log
一、问题 IDEA在编译的时候报Error:(30, 17) java: 找不到符号符号: 变量 log Error:(30, 17) java: 找不到符号 符号: 变量 log 位置: 类 com.mokerson.rabbitmq.config.RabbitMqConfig 二、解决方案 背景:下载其他同事代码时,第一次运行,…...
HTML 基础架构:理解网页的骨架
HTML的文档结构主要由以下几个部分组成:<html>、<head>和<body>。 <html>标签是HTML文档的根元素,用来包裹整个HTML文档的内容。<head>标签用于定义文档的头部,包含了一些元数据和其他不直接显示在页面上的内…...

FPGA学习笔记#5 Vitis HLS For循环的优化(1)
本笔记使用的Vitis HLS版本为2022.2,在windows11下运行,仿真part为xcku15p_CIV-ffva1156-2LV-e,主要根据教程:跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习 从这一篇开始正式进入HLS对C代码的优化笔记 目录 1.循环优化中的基…...

web实操4——servlet体系结构
servlet体系结构 我们基本都只实现service方法,其余几个都不用, 之前我们直接实现servlet接口,所有的方法都必须实现,不用也得写,不然报错,写了又不用当摆设。 能不能只要定义一个service方法就可以&…...

Linux开发讲课48--- Linux 文件系统概览
本文旨在高屋建瓴地来讨论 Linux 文件系统概念,而不是对某种特定的文件系统,比如 EXT4 是如何工作的进行具体的描述。另外,本文也不是一个文件系统命令的教程。 每台通用计算机都需要将各种数据存储在硬盘驱动器(HDD)…...
Node.js 模块详解
模块的概念 Node.js 运行在 V8 JavaScript 引擎上,通过 require() 函数导入相关模块来处理服务器端的各种进程。一个 Node.js 模块可以是一个函数库、类集合或其他可重用的代码,通常存储在一个或多个 .js 文件中。 例如,启动一个 Node.js 服…...
大厂面试真题-说说tomcat的优缺点
Tomcat作为服务器,特别是作为Java Web服务器,具有一系列优点和缺点。以下是对其优缺点的详细分析: 优点 开源免费: Tomcat是一个免费、开源的Web服务器,用户可以在任何环境下自由使用,无需支付任何费用。…...

Linux系统编译boot后发现编译时间与Windows系统不一致的解决方案
现象 如下图,从filezilla软件看虚拟机Linux中编译的uboot.img修改时间与Windows系统时间不同 解决过程 在Linux中查看编译的uboot详细信息,从而得到编译时间。终端输入ls -l后,如下图: 结论 说明在Linux是按照Windows系统时…...

WPS Office手机去广高级版
工具介绍功能特点 WPS Office是使用人数最多的移动办公软件,独有手机阅读模式,字体清晰翻页流畅;完美支持文字,表格,演示,PDF等51种文档格式;新版本具有海量精美模版及高级功能 安装环境 [名称…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...