Qt 实战(4)信号与槽 | 4.1、信号与槽机制

文章目录

  • 一、信号与槽机制
    • 1、基本概念
    • 2、信号与槽函数连接
      • 2.1、connect+宏实现信号与槽连接
      • 2.2、Qt5新connect函数
      • 2.3、使用函数指针
      • 2.4、使用lambda表达式
      • 2.5、使用Qt Creator添加信号的槽函数
    • 3、结论

前言:

Qt信号与槽机制是一种用于处理对象间通信的强大机制,它是Qt框架的核心特性之一。信号与槽机制使得Qt对象可以在不了解彼此的情况下进行通信,这种松耦合的设计思想极大地提高了代码的可重用性和灵活性。

一、信号与槽机制

1、基本概念

在Qt中,一个对象可以发出一个信号,而另一个对象的槽函数可以接收这个信号并作出响应。信号是一个类的成员函数,当某个特定的事件发生时,它会被自动调用。槽函数也是类的成员函数,它可以被信号连接,当信号发出时,槽函数会被自动执行。下面是与信号槽机制相关的基本概念,如下:

1)信号

在Qt中,信号是一个特定的成员函数,用于在某个特定事件发生时被发射(emit)。信号本身并不实现任何功能,它只是表明某个事件已经发生。信号可以被定义为一个类的成员函数,但其实现是由Qt的元对象系统自动完成的。信号的声明通常在类的头文件中进行,使用signals关键字来标记。

2)槽

槽是普通的成员函数,可以被信号触发。当信号被发射时,与之连接的槽函数将被调用。槽函数可以实现具体的功能,比如更新界面、处理数据等。槽函数的声明和普通成员函数一样,但在Qt的元对象系统中需要进行一些特殊的标记,以便与信号进行连接。

2、信号与槽函数连接

信号与槽的连接是通过QObject::connect()函数实现的,需要注意的是,为了使类支持信号与槽机制,需要在类的声明中包含Q_OBJECT宏。下面介绍几种不同的连接方式,如下:

2.1、connect+宏实现信号与槽连接

在Qt4及之前的版本基于connect+宏实现信号与槽绑定,其中发送信号和槽函数需要用 SIGNAL()SLOT() 来进行声明,connect函数声明如下:

QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, 
    const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

下面是一段示例代码,如下:

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

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 登录按键绑定槽函数
    connect(this->ui->btn_ok, SIGNAL(clicked(bool)), this, SLOT(login()));

}

void MainWindow::login()
{
    QString username = ui->lineEdit_username->text();
    QString password = ui->lineEdit_password->text();

    if (username == "jack" && password == "12345") {
        qDebug() << "login success";
    } else {
        qDebug() << "login fail";
    }
}

基于connect+宏实现信号与槽连接,需要注意下面这些问题

  • 声明槽函数要使用private slotspublic slots关键字
  • 信号和槽参数不能包含任何变量名,只能包含类型

2.2、Qt5新connect函数

Qt5推出了新的connect函数,不需要使用SIGNAL()SLOT()宏,可以在编译时做类型检查,connect函数声明如下:

QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, 
    const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

使用这种方法槽函数的声明不需要放到slots中,只要像普通的函数一样声明就可以了,类型需要与信号保持一致,下面给登录按键绑定槽函数,如下:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    // 声明槽函数,与普通的成员函数一样
    void login();

private:
    Ui::MainWindow *ui;
};

绑定槽函数

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
   
    // 登录按键绑定槽函数
    connect(ui->btn_ok, &QPushButton::clicked, this, &MainWindow::login);
}

void MainWindow::login()
{
    qDebug() << "login";
}

2.3、使用函数指针

在Qt 5版本的connect 函数里,信号与槽函数的参数其实都是函数指针,当信号或槽函数有重载时,使用函数指针可以明确告诉编译器使用哪一个重载函数避免歧义

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    // 声明两个同名的login函数
    void login();
    void login(int state);

通过函数指针绑定槽函数

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

    // 定义函数指针(注意:声明指向成员函数的指针时,要增加类作用域)
    void (MainWindow::*pfnLoginSlot)() = &MainWindow::login;

    // 登录按键绑定无参槽函数
    connect(ui->btn_ok, &QPushButton::clicked, this, pfnLoginSlot);
}

void MainWindow::login()
{
    qDebug() << "login";
}

void MainWindow::login(int state)
{
    qDebug() << "login state";
}

2.4、使用lambda表达式

在connect函数中,槽函数参数可以改用Lambda表达式的方式来进行传参。使用 Lambda表达式的好处是代码的书写更加方便快捷,同时不需要在类中对槽函数做任何的声明了

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

    // 使用Lamdbda表达式作为槽函数
    connect(ui->btn_ok, &QPushButton::clicked, this, [=](){
        qDebug() << "login";
    });
}

2.5、使用Qt Creator添加信号的槽函数

通过Qt Creator 界面来完成发送信号和槽函数的连接,比如右键点击一个按钮,然后选择“转到槽”:

在这里插入图片描述

Qt Creator会自动生成如下代码,首先是槽函数的声明:

// 槽函数声明
private slots:
    void on_btn_cancel_clicked(bool checked);

槽函数实现,如下:

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

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

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

void MainWindow::on_btn_cancel_clicked(bool checked)
{
    
}

使用这种方法不需要使用connect函数将信号与槽函数做连接。 这里槽函数的命名有一定的规则,一般是 on_objectname_signal 这样来命名的。这种方法优点是减少了手动敲代码的工作量,缺点是究竟有哪些信号与槽函数做了连接不易被发现,没有connect 函数看起来直观。

3、结论

Qt的信号与槽机制提供了一种强大且灵活的方式来处理对象间的通信,它是Qt框架中不可或缺的一部分。通过信号和槽,开发者可以轻松地构建出响应式、事件驱动的用户界面和应用程序逻辑。

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

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

相关文章

精品KEITHELY6517B参数资料/静电计/高阻计

Keithley 5 位 6517B 静电计/高阻计提供最先进的精度和灵敏度规格&#xff0c;并具有各种功能&#xff0c;可简化高阻和绝缘材料电阻率的测量。Keithley 6517B 的读数速率高达 425 次/秒&#xff0c;可快速、轻松地测量低电平电流。 Keithley 6517B 是更新版本&#xff0c;取代…

Day 18:881. 救生艇

Leetcode 881. 救生艇 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&#xff0c;但条件是这些人的重量之和最多为 limit。 返回 承载所有人所需的最小船数 。 这里有一个条…

图解Mamba——从流体力学的角度理解Mamba

1.Transformer的问题 上面是Transformer的网络结构。对于一句话的每个单词&#xff0c;都需要跟所有单词算注意力机制。因此注意力机制的计算复杂度为 O ( n 2 ) O(n^2) O(n2)&#xff0c;其中 n n n为句子的长度&#xff0c;即单词(符号)的个数。如下图所示。 所以这也是现在…

Latex | 数学公式

Latex 最近在学习使用 LaTeX 来敲公式&#xff0c;写材料。说实话&#xff0c;这个工具在写公式方面&#xff0c;确实堪称神器&#xff01;不只是我&#xff0c;连爱因斯坦要是看到它&#xff0c;估计都会点个赞。 在这里&#xff0c;我也得给大家分享一个宝藏网址&#xff1…

打工人必看!AI+PS插件轻松搞定电商产品图!保姆教程来啦!

大家好哇&#xff01;我是你们的AIGC测评博主米兔&#xff01; 在当今电商蓬勃发展的时代&#xff0c;一张高质量、具有吸引力的产品图能够迅速吸引消费者的目光&#xff0c;提升购买欲望。今天&#xff0c;我们就来探讨一下如何利用AI结合PS插件制作电商产品图&#xff0c;让…

斜率优化详解

斜率优化 [HNOI2008] 玩具装箱 状态转移方程&#xff1a; f i m i n ( f i , f j ( s u m i i − s u m j − j − L ) 2 ) i > j f_imin(f_i,f_j(sum_ii-sum_j-j-L)^2){i>j} fi​min(fi​,fj​(sumi​i−sumj​−j−L)2)i>j 设A为 s u m i i sum_ii sumi​i&…

计算机二级Access选择题考点

在Access中&#xff0c;若要使用一个字段保存多个图像、图表、文档等文件&#xff0c;应该设置的数据类型是附件。在“销售表"中有字段:单价、数量、折扣和金额。其中&#xff0c;金额单价x数量x折扣&#xff0c;在建表时应将字段"金额"的数据类型定义为计算。若…

C语言调用so/dll动态库

文章目录 windows系统linux系统windows 与 linux下 C 调用动态库的差异 C语言调用动态链接库 windows系统 windows系统下&#xff0c;C语言调用win下的动态库dll&#xff0c;使用头文件<windows.h>。 准备基础C代码 lauf.c #include <stdio.h>// 定义函数&#x…

一键把家里孩子的涂鸦变为动画

最近&#xff0c;发现一款可以让涂鸦变成动画的工具&#xff08;Animated Drawings&#xff09;。 家里有孩子喜欢涂鸦的有福了&#xff0c;这是一个新的增加亲子互动的工具&#xff0c;可以让你孩子的涂鸦变成动画&#xff0c;动起来。 生成动画的过程非常简单&#xff0c;只…

Python解析Word文档的自动编号

关于自动编号的知识可以参考《在 Open XML WordprocessingML 中使用编号列表》 链接&#xff1a;https://learn.microsoft.com/zh-cn/previous-versions/office/ee922775(voffice.14) python-docx库并不能直接解析出Word文档的自动编号&#xff0c;因为原理较为复杂&#xff…

Macbook M芯片Maven的安装与配置

Macbook M芯片Maven的安装与配置 下载 搜索Maven 进入网站 https://maven.apache.org/download.cgi 点击Download 点击如下链接进行下载&#xff1b; 将下载好的文件放到你的指定位置 双击进行解压 配置环境变量 进入终端 在终端中输入 open ~/.bash_profile输入以下内…

CCNA 0基础入门

OSI & TCP/IP OSI参考模型 TCP/IP协议 应用层 ------↓表示层 ------>应用层会话层 ------↑传输层 ------>传输层网络层 ------>网络互联层链路层 ------>网络接口层物理层 ------>↑ 物理层 传输的信号以及网线以及接线 主要作用是产生并检测电…

16 DTLS协议

加密解密基本概念 什么是非对称加密 什么是公钥 这个就是谁都能获得的钥匙什么是私钥 只有一个人能获得 非对称加密就是公钥上的锁&#xff0c;私钥才能打开&#xff0c;私钥上的锁公钥才能打开。比如说就是地下党接头的时候&#xff0c;把一个信息放在盒子里&#xff0c;然…

pikachu靶场上的暴力破解

目录 一、暴力破解 基于表单的暴力破解 验证码绕过(on server) ​编辑 验证码绕过(on client) ​编辑 token防爆破? 二、暴力破解的相关知识点 (1)Burte Force&#xff08;暴力破解&#xff09;概述 (2)验证码的绕过原理 【验证码机制原理】 【客户端可能存在的安全…

智能型程控直流电子负载的介绍

智能型程控直流电子负载是一种高精度、高稳定性的电子设备&#xff0c;主要用于模拟各种实际负载情况&#xff0c;对电源设备进行测试和调试。它能够精确控制电流、电压、功率等参数&#xff0c;以满足不同应用场景的需求。 智能型程控直流电子负载的主要特点有以下几点&#x…

连接查询-外连接(FULL JOIN)、内连接(JOIN)、自身连接

一、表与表之间存在着某种联系&#xff0c;如果一个查询必须在多个表之间完成&#xff0c;则需要用到连接查询 二、连接查询的SQL查询语句 格式&#xff1a; SELECT A1&#xff0c;A2&#xff0c;...&#xff0c;Am FROM R1&#xff0c;R2&#xff0c;..&#xff0c;Rn WH…

推荐这3个APP,帮助你成长

扇贝阅读 当年考英语四级&#xff0c;扇贝阅读帮了很大的帮&#xff0c;这个应用我推荐给了好多同学使用&#xff0c;大家一致反馈不错。 提供很多原版的英文原著供学习&#xff0c;还自带翻译功能&#xff0c;并且提供单词本&#xff0c;遇到不懂的单词可以纪录到单词本中&am…

车载网络安全指南 网络安全框架(二)

返回总目录->返回总目录<- 目录 一、概述 二、网络安全组织管理 三、网络安全活动 四、支撑保障 一、概述 汽车电子系统网络安全活动框架包含汽车电子系统网络安全活动、组织管理以及支持保障。其中,网络安全管理活动是框架的核心,主要指汽车电子系统生命周期各阶段…

Day 14:2938. 区分黑球和白球

Leetcode 2938. 区分黑球和白球 桌子上有 n 个球&#xff0c;每个球的颜色不是黑色&#xff0c;就是白色。 给你一个长度为 n 、下标从 0 开始的二进制字符串 s&#xff0c;其中 1 和 0 分别代表黑色和白色的球。 在每一步中&#xff0c;你可以选择两个相邻的球并交换它们。 返…

E10:流程明细表表单字段值变化触发事件

效果– //window.WeFormSDK.showMessage("这是一个E10的提示", 3, 2);// 获取表单实例const weFormSdk window.WeFormSDK.getWeFormInstance();// 获取主表字段fieldIdconst bt weFormSdk.convertFieldNameToId("bt");const lcbh weFormSdk.convertFi…