QT的核心——信号与槽

目录

回顾C 语言信号

1、信号与槽

2、关联信号与槽

2.1自动关联信号与槽

2.2手动关联信号与槽

2.3断开信号与槽

3、自定义信号

3.1自定义信号使用条件

3.2自定义槽函数使用条件

4、信号与槽参数传递

4.1自定义一个带参的信号

4.2关联带参的信号与槽

4.3发送一个带参的信号

5、信号与槽的相互关联

6、lambda表达式

 lambda 表达式的应用

 7、lambda 与 信号和槽


回顾C 语言信号

signal(设置信号处理方式)

功能:注册一个信号处理函数,当收到该信号后,就会触发handler 函数

表头文件 #include<signal.h>

定义函数 void *signal(int signum,void(* handler)(int));

signum : 需要捕捉的信号。

handler : 收到信号后执行的函数

1.捕捉的信号能自定义吗? 不可以,只能使用系统预定义好的信号

2.信号可以传输数据吗? 不可以,信号只负责通知

所以QT 在 C 语言的信号基础进行封装,把上述两个问题都解决了。 在QT 中用户可以自定义信号, 在QT 中用户可以通过信号与槽传递参数。

信号:各种事件

槽: 响应信号的动作

1、信号与槽

当某个事件发生后,如某个按钮被点击了一下,它就会发出一个被点击的信号(signal)。

某个对象接收到这个信号之后,就会做一些相关的处理动作(称为槽slot)。

但是Qt对象不会无故收到某个信号,要想让一个对象收到另一个对象发出的信号,这时候需要建立连接(connect)

//QT的四个信号

  1. pressed():鼠标按下时触发。对应的函数是 mousePressEvent()。
  2. clicked():鼠标松开时触发。如果鼠标拖拽到按钮区域之外释放则不会触发。对应的函数是 mouseReleaseEvent()。一般情况下 connect 槽函数时使用该信号。
  3. released():鼠标松开时触发。即使鼠标拖拽到按钮区域之外释放也会触发。对应的函数是 mouseReleaseEvent()。
  4. toggled():设置 setCheckable(true) 后再单击按钮才会触发该信号。一般用于多个按钮组成 QButtonGroup 并且 setExclusive(true) 设置按钮间互斥。 正常情况下单击按钮,响应顺序为:pressed() — about 215ms — released() — almost 0ms — clicked()。

2、关联信号与槽

关联的方法有两种:自动关联,手动关联。下面对此进行一次次介绍

2.1自动关联信号与槽

在项目 增加信号和槽的方法一:在UI设计师中增加

第一步:右击控件,在弹出的对话框,

在下拉列表中,选择"转到槽",会弹出选择对话框

第二步:选择自己信号

会自动生成槽函数(.h和.cpp)

第三步:当点击相应的控件时,对应的槽函数就会被调用,从面是实现动态交互的效果

槽函数

2.2手动关联信号与槽

QMetaObject::Connection QObject::connect(
    const QObject *sender,
    const char *signal,
    const QObject *receiver,
    const char *method,
    Qt::ConnectionType type = Qt::AutoConnection
);
其中,sender 表示信号发送者,signal 表示信号名,receiver 表示信号接收者,method 表示槽函数名,type 表示连接类型

type参数的值

描述

解释

Qt::DirectConnection

直接连接

即在信号发出时直接调用槽函数,槽函数会立即执行,而不管当前的线程是否与信号发出者在同一个线程

Qt::QueuedConnection

排队连接

将信号事件放入接收对象的事件队列中,槽函数会在事件循环处理时被执行,适用于跨线程的连接

Qt::BlockingQueuedConnection

阻塞排队连接

槽函数会在接收对象的线程中执行,并且当前线程会阻塞,直到槽函数执行完成

Qt::AutoConnection

自动连接

如果信号发送者和接收者在同一个线程,使用直接连接,否则使用排队连接

Qt::UniqueConnection

唯一连接

已经存在相同的连接,则不会创建新的连接,可以避免重复连接导致的问题,如重复执行槽函数等

 在QT4和QT5中,手动关联有着意义重大的调整,QT4不会检查信号与槽的参数是否匹配,而QT5会自动检查信号与槽的参数是否匹配。

下面给出QT4和QT5的关联例子:

QT4:

 //手动关联信号与槽        this 表示的是当前窗体,MainWindow
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));

QT5:

connect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::show_msg);

2.3断开信号与槽

语法:

语法: QT4: disconnect(信号发送者地址,SIGNAL(信号名(参数列表)),信号接收者地址,SLOT(槽名称(参数列表)));

QT5: disconnect(信号发送者地址,&发送者类名::信号名,信号接收者地址,&接受者类名::槽名称);

void MainWindow::on_pushButton_2_clicked()
{
    //取消信号与槽的关联 QT4
    // disconnect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));


    //取消信号与槽的关联 QT5
    disconnect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::on_pushButton_clicked);

    //因为自动关联,QT软件采用的是QT4的语法关联,所以取消只能用QT4 。
    //关联时使用了那种方法,取消时要一致!!

    qDebug() << "取消关联";
}

注意:使用自动关联的时候,QT软件采用的是QT4的语法关联,所以取消关联只能用QT4;使用手动关联的时候,关联时使用了那种方法,取消时要一致

3、自定义信号

在QT中,信号是可以自定义的,语法如下:

//在xxx.h头文件中 声明信号 
signals:  
   void 信号名(参数列表); 

注意:信号只需要声明不需要定义!!!

 但是可以看到定义信号的时候可以参数,参数的类型在信号定义的时候必须已经确定,而且不能改变,信号默认只能传递基本的类型如下(列举部分):

int:整数类型

double:双精度浮点数类型

QString:字符串类型

QDate:日期类型

QTime:时间类型

QColor:颜色类型

在C++中,参数支持默认参数,那么在QT的信号定义时,当然也可以为参数设置默认值

定义完自定义信号之后,需要代码来控制发送信号,发送语法如下:

//使用  emit 信号名(参数列表); 发送信号  
emit  mysig(); //发送一个mysig信号 

在发出信号时,如果没有指定参数,则使用默认值。

自定义信号与槽的关联和上面的关联是类似的:

 //信号在那个类中定义的,该类就是发送者
    connect(this,SIGNAL(mysig()),this,SLOT(getsig()));

    //发送信号
    emit  mysig();

//温馨提示:信号的发送必须在"关联后"发送,否则该信号失效 

3.1自定义信号使用条件

  1. 声明在类的signals域下
  2. 没有返回值,void类型的函数
  3. 只有函数声明,没有定义
  4. 可以有参数,可以重载
  5. 通过emit关键字来触发信号,形式:emit object->sig(参数);

3.2自定义槽函数使用条件

  1. qt4 必须声明在 private/public/protected slots域下面,qt5之后可以声明public下,同时还可以是静态的成员函数,全局函数,lambda表达式
  2. 没有返回值,void类型的函数
  3. 不仅有声明,还得要有实现
  4. 可以有参数,可以重载

4、信号与槽参数传递

4.1自定义一个带参的信号

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
//自定义一个带参的信号
signals:
  void mysig(int a);
                                      //注意:信号与槽的参数类型必须匹配!! 
//声明一个带参的槽函数
public  slots: 
  void getsig(int a);  
    
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

4.2关联带参的信号与槽

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //关联带参的信号与槽,信号与槽的参数都需要在关联是列举出来 
    connect(this,SIGNAL(mysig(int)),this,SLOT(getsig(int)));
}

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

4.3发送一个带参的信号

emit  mysig(10010); 

 注意事项:

  1. 信号参数的类型必须要与槽函数的类型匹配 参数类型不匹配会发生报错: MainWindow::mysig(QString) --> MainWindow::myslot(int)
  2. 信号参数的个数必须大于槽函数参数的个数(理解:能少接受发来的信号,不能多接受发来的信号) 槽参数的个数大于信号参数个数 : MainWindow::mysig(int) --> MainWindow::myslot(int,int,int)

5、信号与槽的相互关联

6、lambda表达式

  1. capture 子句(在 C++ 规范中也称为 Lambda 引导。)
  2. 参数列表(可选)。 (也称为 Lambda 声明符)
  3. mutable 规范(可选)。
  4. 异常规范(可选)。
  5. 后面的-返回值-类型(可选)。
  6. Lambda 体。
语法:
auto func = [capture] (params) opt -> ret 
            { func_body; };

func是可以当作lambda表达式的名字,作为一个函数使用
capture是捕获列表
params是参数表
opt是函数选项(mutable之类)
ret是返回值类型
func_body是函数体。  
    
capture是捕获列表:
[]不捕获任何变量
[&]引用捕获,捕获外部作用域所有变量,在函数体内当作引用使用,可以修改值
[=]值捕获,捕获外部作用域所有变量,在函数内内有个副本使用  ,不可以修改值
[=, &a]值捕获外部作用域所有变量,按引用捕获a变量
[a]只值捕获a变量,不捕获其它变量
[this]捕获当前类中的this指针
    
opt选择:
int a = 0;
auto f1 = [=](){ return a; }; // 值捕获a
cout << f1() << endl;
auto f2 = [=]() { return a++; }; // 修改按值捕获的外部变量,error
auto f3 = [=]() mutable { return a++; }; //添加mutable 选项可以修改

 lambda 表达式的应用

#include <iostream>
#include <list>
using  namespace std;

int main() {
    
    list<int> vec;
    vec.push_back(10);
    vec.push_back(45);
    vec.push_back(4);
    vec.push_back(48);

    vec.sort(); 

    for(int i:vec)
    {
        cout << i << endl;
    }
    //自定义排序的规则 
    vec.sort([](int a,int b){return a>b;});

    for(int i:vec)
    {
        cout << i << endl;
    }
}

基础写法

 数据捕获问题

 7、lambda 与 信号和槽

QT 中的一些简单功能的槽函数可以直接设计为 lambda 表达式,这样就不用在头文件声明槽,在源文件定义槽。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //手动关联信号与槽 , 去头文件声明 myslot  ,再定义 myslot  很麻烦
    //connect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::myslot);


    //把槽函数修改为 lambda表达式
    connect(ui->pushButton,&QPushButton::clicked,this,[](){qDebug() << "按钮点击";});

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

奥威BI数据可视化工具:个性化定制,打造独特大屏

每个人都有自己独特的审美&#xff0c;因此即使是做可视化大屏&#xff0c;也有很多人希望做出不一样的报表&#xff0c;用以缓解审美疲劳的同时提高报表浏览效率。因此这也催生出了数据可视化工具的个性化可视化大屏制作需求。 奥威BI数据可视化工具&#xff1a;个性化定制&a…

[线程/C++]线程同(异)步和原子变量

文章目录 1.线程的使用1.1 函数构造1.2 公共成员函数1.2.1 get_id()1.2.2 join()2.2.3 detach()2.2.5 joinable()2.2.6 operator 1.3 静态函数1.4 call_once 2. this_thread 命名空间2.1 get_id()2.2 sleep_for()2.3 sleep_until()2.4 yield() 3. 线程同步之互斥锁3.1 std:mute…

Open cv C++安装

注意;要退出conda的虚拟环境 依赖 1.更新系统 sudo apt-get update sudo apt-get upgrade 2.安装相关的依赖 sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install libjpeg-de…

C语言 poll多路复用

NAME poll, ppoll - wait for some event on a file descriptor SYNOPSIS #include <poll.h> 函数原型&#xff1a; int poll(struct pollfd *fds, nfds_t nfds, int timeout); #define _GNU_SOURCE /* See feature_test_macros(7) */ …

网格(mesh)点跟踪及在贴图中的应用

本文介绍网格跟踪的思路及其在贴图中的使用效果。网格跟踪即跟踪所有的网格点&#xff0c;然后根据网格点估算某一点的变形&#xff0c;相较于曲面跟踪可以在保证一定精度条件下大幅提高处理速度。这里介绍一种简单的网格跟踪思路&#xff0c;效果如下图所示&#xff1a; 创建网…

vue3中使用第三方插件mitt实现任意组件通讯

vue3中使用第三方插件mitt实现任意组件通讯 组件通讯是vue3组合式开发的核心之一&#xff0c;现在我在写代码时&#xff0c;一个组件的代码超过了200行&#xff0c;基本都会拆分组件。组件拆分后&#xff0c;组件之间的通讯就很重要&#xff0c;总结了一下&#xff0c;目前有这…

微服务—Eureka注册中心

eureka相当于是一个公司的管理人事HR,各部门之间如果有合作时&#xff0c;由HR进行人员的分配以及调度&#xff0c;具体选哪个人&#xff0c;全凭HR的心情&#xff0c;如果你这个部门存在没有意义&#xff0c;直接把你这个部门撤销&#xff0c;全体人员裁掉&#xff0c;所以不想…

vue根据template结构自动生成css/scss/less样式嵌套

vscode搜索安装插件&#xff1a;AutoScssStruct4Vue

mqtt协议

MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&#xff09;模式的"轻量级"通讯协议&#xff0c;该协议构建于TCP/IP协议上&#xff0c;由IBM在19…

特殊数字专题

特殊数字 1.奇数2.偶数3.完数4.素数5.回文数6.水仙花数7.中位数9.随机数11.求年份&#xff1a;闰年12.求数字&#xff1a;两个整数的最大公约数及最小公倍数 1.奇数 代码案例&#xff1a; //输出所有1-1000之间的奇数 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h&…

如何避免爬虫IP被屏蔽

各位爬友们好&#xff0c;作为一名专业的爬虫代理提供者&#xff0c;我要和大家分享一些避免爬虫IP被屏蔽的实用技巧。你知道吗&#xff0c;当我们爬取数据的时候&#xff0c;很容易被目标网站识别出来并封禁我们的IP地址&#xff0c;导致无法继续爬取数据。这个问题困扰了很多…

qt实现9×9数独游戏

qt实现的数独小游戏&#xff0c;资源有可下载直接跑的exe&#xff08;enigma已经打包好&#xff09;&#xff0c;源码可私信 部分代码 #include "widget.h" #include "ui_widget.h" #include"form.h" #include<QDebug> #include<QPush…

【广州华锐视点】AR配电所巡检系统:可视化巡检利器

随着科技的发展&#xff0c;人工智能、大数据等技术逐渐应用于各个领域&#xff0c;为人们的生活带来便利。在电力行业&#xff0c;AR(增强现实)技术的应用也日益广泛。AR配电所巡检系统作为一种新型的巡检方式&#xff0c;可以实现多种功能&#xff0c;提高巡检效率&#xff0…

[SWPUCTF 2022 新生赛]ez_ez_php

这段代码是一个简单的PHP文件处理脚本。让我们逐行进行分析&#xff1a; error_reporting(0); - 这行代码设置了错误报告的级别为0&#xff0c;意味着不显示任何错误。 if (isset($_GET[file])) { - 这行代码检查是否存在一个名为"file"的GET参数。 if ( substr($_…

用pytorch实现Resnet

ResNet&#xff08;Residual Network&#xff09;是一种深度卷积神经网络架构&#xff0c;由Kaiming He等人于2015年提出。它在计算机视觉领域引起了革命性的变革&#xff0c;使得训练更深的神经网络成为可能&#xff0c;超越了传统网络架构的限制。 ResNet的主要创新在于…

第G1周:生成对抗网络(GAN)入门

&#x1f4cc; 基础任务&#xff1a;了解什么是生成对抗网络&#xff08;GAN&#xff09; 学习本文代码&#xff0c;并跑通代码 &#x1f388;进阶任务&#xff1a; 调用训练好的模型生成新图像 目录 一、理论基础 1.1生成器 1.2判别器 1.3基本原理 二、前期准备工作 2.…

基于CNN卷积神经网络的口罩检测识别系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................ % 循环处理每张输入图像 for…

汽车租赁管理系统/汽车租赁网站的设计与实现

摘 要 租赁汽车走进社区&#xff0c;走进生活&#xff0c;成为当今生活中不可缺少的一部分。随着汽车租赁业的发展&#xff0c;加强管理和规范管理司促进汽车租赁业健康发展的重要推动力。汽车租赁业为道路运输车辆一种新的融资服务形式、广大人民群众一种新的出行消费方式和…

Centos7 配置Docker镜像加速器

docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六):docker 网络及数据卷设置 docker实战(七):docker 性质及版本选择 认知升…

区块链中slot、epoch、以及在slot和epoch中的出块机制,分叉原理(自己备用)

以太坊2.0中有两个时间概念&#xff1a;时隙槽slot 和 时段&#xff08;周期&#xff09;epoch。其中一个slot为12秒&#xff0c;而每个 epoch 由 32 个 slots 组成&#xff0c;所以每个epoch共384秒&#xff0c;也就是 6.4 分钟。 对于每个epoch&#xff0c;使用RANDAO伪随机…