113.QT中的信号槽

目录

一、信号和槽概述

信号和槽的基本概念:

信号和槽的关系:

二、标准信号槽使用

三、自定义信号槽的使用

自定义信号:

自定义槽:

四、Lambda表达式

[1.Lambda 表达式不带参数和返回值:](#1.Lambda 表达式不带参数和返回值:)

[2.Lambda 表达式带参数:](#2.Lambda 表达式带参数:)

[3.Lambda 表达式带参数和返回值:](#3.Lambda 表达式带参数和返回值:)

[4.Lambda 表达式带捕获列表:](#4.Lambda 表达式带捕获列表:)


一、信号和槽概述

信号和槽是Qt框架中一种用于处理事件和实现对象间通信的机制。这种机制使得对象能够在特定事件发生时通知其他对象,并让其他对象能够响应这些事件。

信号和槽的基本概念:

  1. 信号(Signal):

    • 信号是对象发出的通知,表示某个特定事件发生了。信号通常由 emit 关键字发射。
    • 一个信号可以与多个槽关联,多个对象可以连接到同一个信号。
  2. 槽(Slot):

    • 槽是一个特殊的成员函数,用于处理与之关联的信号。槽函数的名称以 on_ 开头是一种常见的命名约定,但并非必须。
    • 槽函数的签名必须与与之关联的信号的签名相匹配。

信号和槽的关系:

在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,好比牛郎和织女想要相会必须要有喜鹊为他们搭桥一样。在Qt中我们需要使用QOjbect类中的connect函数进二者的关联。

信号和槽是Qt框架中一种强大的机制,使得对象能够以灵活而松散耦合的方式进行通信和事件处理。这种机制在Qt应用程序中广泛应用,特别是在用户界面开发和多线程编程中。

连接信号和槽的connect()函数原型如下:

cpp 复制代码
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);
  • sender: 这是发射信号的对象。当 sendermySignal 信号被发射时,与之关联的槽函数将被调用。

  • signal:属于sender对象, 信号是一个函数, 这个参数的类型是函数指针, 信号函数地址

  • receiver: 这是接收信号的对象。当 sender 对象发射 mySignal 信号时,与之连接的 receiver 对象的 mySlot 槽函数将被调用。

  • method: 属于receiver对象, 当检测到sender发出了signal信号,receiver对象调用method方法,信号发出之后的处理动作

二、标准信号槽使用

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->closeBut,&QPushButton::clicked,this,&MainWindow::close);
}

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

这段代码是在Qt中使用 connect 函数,将一个按钮的点击事件(clicked信号)与 MainWindow 类的 close 槽函数连接起来。当按钮被点击时,MainWindowclose 槽函数将被调用,关闭主窗口。

connect 函数:

cpp 复制代码
connect(ui->closeBut, &QPushButton::clicked, this, &MainWindow::close);
  • ui->closeBut: 这是一个指向 QPushButton 对象的指针,表示窗口中的一个按钮。
  • &QPushButton::clicked: 这是按钮的 clicked 信号。QPushButton 类的 clicked 信号在按钮被点击时触发。
  • this: 这是当前对象,即 MainWindow 的实例。
  • &MainWindow::close: 这是 MainWindow 类的 close 槽函数。在这里,它与按钮的 clicked 信号关联。

close 槽函数:

cpp 复制代码
void MainWindow::close()
{
    // 槽函数的实现
    QMainWindow::close();  // 关闭主窗口
}
  1. 当按钮被点击时,MainWindow::close 槽函数被调用,关闭主窗口。

总体而言,这段代码建立了一个很简单的连接,使得当按钮被点击时,主窗口将被关闭。

三、自定义信号槽的使用

自定义信号:

在Qt中,可以自定义信号和槽,以便在你的应用程序中实现自定义的事件处理机制,同样还是使用connect()对自定义的信号槽进行连接。

如果想要在QT类中自定义信号槽, 需要满足一些条件, 并且有些事项也需要注意:

  • 要编写新的类并且让其继承Qt的某些标准类
  • 这个新的子类必须从QObject类或者是QObject子类进行派生
  • 在定义类的头文件中加入 Q_OBJECT 宏

在Qt中信号的本质是事件, 但是在框架中也是以函数的形式存在的, 只不过信号对应的函数只有声明, 没有定义。如果Qt中的标准信号不能满足我们的需求,可以在程序中进行信号的自定义,当自定义信号对应的事件产生之后,认为的将这个信号发射出去即可(其实就是调用一下这个信号函数)。

自定义槽:

槽函数就是信号的处理动作,在Qt中槽函数可以作为普通的成员函数来使用。如果标准槽函数提供的功能满足不了需求,可以自己定义槽函数进行某些特殊功能的实现。自定义槽函数和自定义的普通函数写法是一样的。

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

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

    m_me=new Me;
    m_girl=new girlfriend;

    // 连接女朋友对象的hungry信号到Me对象的eat槽函数
    connect(m_girl,&girlfriend::hungry,m_me,&Me::eat);

    // 连接女朋友对象的hungry信号到MainWindow对象的eatSlot槽函数
    connect(m_girl,&girlfriend::hungry,this,&MainWindow::eatSlot);

    // 连接按钮的clicked信号到MainWindow对象的hungrySlot槽函数
    connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);

    // 连接按钮的clicked信号到MainWindow对象的close槽函数
    connect(ui->closeBut,&QPushButton::clicked,this,&MainWindow::close);//通过点击事件 关闭窗口
}

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

void MainWindow::hungrySlot()
{
    //发射自定义信号
    m_girl->hungry();
}

void MainWindow::eatSlot()
{
    qDebug()<<"我带你去吃海鲜...";
}

这个例子创建了一个主窗口,包含两个按钮(ui->hungryui->closeBut)。其中,ui->hungry 按钮模拟女朋友饿了,点击按钮会发射女朋友对象的 hungry 信号。ui->closeBut 按钮用于关闭窗口。

连接的关系如下:

  • ui->hungry 按钮被点击时,会触发 MainWindow::hungrySlot 槽函数,该槽函数通过发射 girlfriend::hungry 信号通知女朋友对象饿了。
  • 女朋友对象的 hungry 信号被连接到两个槽函数:Me::eatMainWindow::eatSlot。这两个槽函数在信号被触发时执行相应的操作。

四、Lambda表达式

Lambda 表达式是一种在 C++ 中引入的匿名函数的语法糖,它允许在需要函数对象的地方直接定义一个匿名函数,而不必显式地声明一个函数,Qt是完全支持c++语法的, 因此在Qt中也可以使用Lambda表达式。。Lambda 表达式的基本形式如下:

cpp 复制代码
[capture](parameters) -> return_type {
    // 函数体
}

其中:

  • capture:捕获列表,用于指定在 lambda 表达式中可见的外部变量。可以通过值捕获、引用捕获,或者混合捕获。
  • parameters:参数列表,与普通函数的参数列表类似。
  • return_type:返回类型,指定 lambda 表达式的返回类型。
  • 函数体:包含实际代码的部分。

关于Lambda表达式的细节介绍:

1.捕获列表: 捕获一定范围内的变量

  • [] - 不捕捉任何变量
  • [&] - 捕获外部作用域中所有变量, 并作为引用在函数体内使用 (按引用捕获)
  • [=] - 捕获外部作用域中所有变量, 并作为副本在函数体内使用 (按值捕获)
  • 拷贝的副本在匿名函数体内部是只读的
  • [=, &foo] - 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo
  • [bar] - 按值捕获 bar 变量, 同时不捕获其他变量
  • [&bar] - 按引用捕获 bar 变量, 同时不捕获其他变量
  • [this] - 捕获当前类中的this指针
  • 让lambda表达式拥有和当前类成员函数同样的访问权限
  • 如果已经使用了 & 或者 =, 默认添加此选项

2.参数列表: 和普通函数的参数列表一样

3.opt 选项 --> 可以省略

  • mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
  • exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用throw();

4.返回值类型:

  • 标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。

5.函数体:

  • 函数的实现,这部分不能省略,但函数体可以为空。

1.Lambda 表达式不带参数和返回值:

cpp 复制代码
[] {
    // 代码块
};

2.Lambda 表达式带参数:

cpp 复制代码
[](int x, int y) {
    return x + y;
};

3.Lambda 表达式带参数和返回值:

cpp 复制代码
[](int x, int y) -> int {
    return x + y;
};

4.Lambda 表达式带捕获列表:

cpp 复制代码
int a = 10;
[](int x) {
    return x + a;
};
相关推荐
爱吃喵的鲤鱼8 分钟前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
DARLING Zero two♡34 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
7年老菜鸡35 分钟前
策略模式(C++)三分钟读懂
c++·qt·策略模式
Gu Gu Study37 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
芊寻(嵌入式)1 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
有梦想的咸鱼_1 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
海阔天空_20131 小时前
Python pyautogui库:自动化操作的强大工具
运维·开发语言·python·青少年编程·自动化
天下皆白_唯我独黑1 小时前
php 使用qrcode制作二维码图片
开发语言·php
夜雨翦春韭1 小时前
Java中的动态代理
java·开发语言·aop·动态代理