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;
};
相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript