Qt信号和信号槽(二)

文章详细介绍了Qt中的信号槽机制,包括一个信号如何连接多个槽函数,信号如何连接信号以及槽函数连接多个信号的情况。同时,文章还探讨了C++11的Lambda表达式在Qt中的使用,包括其语法格式、捕获列表和调用方式,展示了Lambda表达式如何增强代码的灵活性和效率。
摘要由CSDN通过智能技术生成

目录

信号槽使用拓展

示例1(一个信号可以对应多个槽函数)(在上篇文章的代码中进行修改):

 示例2(用信号连接信号):

 信号槽的连接方式

示例:

Lambda表达式

语法格式

定义和调用

信号槽使用拓展

一个信号可以连接多个槽函数, 发送一个信号有多个处理动作

        需要写多个connect()连接

        槽函数的执行顺序是随机的,和connect函数的调用顺序没有关系

        信号的接收者可以是一个对象,也可以是多个对象

一个槽函数可以连接多个信号,多个不同的信号,处理动作是相同的

        需要写多个connect()连接

信号可以连接信号

        信号接收者可以不处理接收的信号,而是继续发射新的信号,这相当于传递了数据,并没有对数据进行处理

connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::siganl-new);

信号槽是可以断开的

disconnect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);
示例1(一个信号可以对应多个槽函数)(在上篇文章的代码中进行修改):

在mainwindow.h中再添加一个槽函数

 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "test.h"
#include "test01.h"
#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    //添加need按钮的槽函数
    void needSlot();

    void need1Slot();

private:
    Ui::MainWindow *ui;

    Test01* m_whatnd;
    Test* m_need;
};
#endif // MAINWINDOW_HS

到mainwindow.cpp中定义并进行连接

 

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_whatnd = new Test01;
    m_need = new Test;
    connect(m_need,&Test::need,m_whatnd,&Test01::what_need);
    connect(m_need,&Test::need,this,&MainWindow::need1Slot);
    connect(ui->need,&QPushButton::clicked,this,&MainWindow::needSlot);

}

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

void MainWindow::needSlot()
{
    //发射自定义信号
    emit m_need->need();

}

void MainWindow::need1Slot()
{
    qDebug()<<"你什么都不需要";
}

运行程序,应用程序输出两条语句:

 示例2(用信号连接信号):

对mainwindow.cpp中的信号连接进行修改

 运行结果和原先一样:

 信号槽的连接方式

Qt5的连接方式

// 语法:
QMetaObject::Connection QObject::connect(
    	const QObject *sender, PointerToMemberFunction signal, 
        const QObject *receiver, PointerToMemberFunction method, 
		Qt::ConnectionType type = Qt::AutoConnection);

// 信号和槽函数也就是第2,4个参数传递的是地址, 编译器在编译过程中会对数据的正确性进行检测
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

示例:

在test01.h中进行函数重载

 在mainwindow.cpp中做以下修改

 

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_whatnd = new Test01;
    m_need = new Test;
    void(Test::*test1)(QString) = &Test::need;
    void(Test::*test2)(QString) = &Test::need;
    void(Test01::*mypoint)(QString) = &Test01::what_need;
    connect(m_need,test2,m_whatnd,mypoint);
    connect(m_need,test2,this,&MainWindow::need1Slot);
    //信号连接信号
    //connect(ui->need,&QPushButton::clicked,m_need,&Test::need);
    connect(ui->need,&QPushButton::clicked,this,&MainWindow::needSlot);

}

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

void MainWindow::needSlot()
{
    //发射自定义信号
    emit m_need->need();
    m_need->need("吃饭");

}

void MainWindow::need1Slot()
{
    qDebug()<<"你什么都不需要";
}

运行结果:

 

 

Lambda表达式

Lambda表达式是 C++ 11 最重要也是最常用的特性之一,是现代编程语言的一个特点,简洁,提高了代码的效率并且可以使程序更加灵活,Qt是完全支持c++语法的, 因此在Qt中也可以使用Lambda表达式。

语法格式

Lambda表达式就是一个匿名函数, 语法格式如下:

[capture](params) opt -> ret {body;};
    - capture: 捕获列表
    - params: 参数列表
    - opt: 函数选项
    - ret: 返回值类型
    - body: 函数体

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

  1. 捕获列表: 捕获一定范围内的变量
    • [] - 不捕捉任何变量
    • [&] - 捕获外部作用域中所有变量, 并作为引用在函数体内使用 (按引用捕获)
    • [=] - 捕获外部作用域中所有变量, 并作为副本在函数体内使用 (按值捕获)
      • 拷贝的副本在匿名函数体内部是只读的
    • [=, &foo] - 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo
    • [bar] - 按值捕获 bar 变量, 同时不捕获其他变量
    • [&bar] - 按引用捕获 bar 变量, 同时不捕获其他变量
    • [this] - 捕获当前类中的this指针
      • 让lambda表达式拥有和当前类成员函数同样的访问权限
      • 如果已经使用了 & 或者 =, 默认添加此选项
  2. 参数列表: 和普通函数的参数列表一样
  3. opt 选项 –> 可以省略
    • mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
    • exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用throw();
  4. 返回值类型:
    • 标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略
  5. 函数体:
    • 函数的实现,这部分不能省略,但函数体可以为空。
定义和调用

因为Lambda表达式是一个匿名函数, 因此是没有函数声明的, 直接在程序中进行代码的定义即可, 但是如果只定义匿名函数在程序执行过程中是不会被调用的。

// 匿名函数的定义, 程序执行这个匿名函数是不会被调用的
[](){
    qDebug() << "hello, 我是一个lambda表达式...";
};

// 匿名函数的定义+调用:
int ret = [](int a) -> int
{
    return a+1;
}(100);  // 100是传递给匿名函数的参数

Lambda表达式的捕获列表中也就是 []内部添加不同的关键字, 就可以在函数体中使用外部变量了。

// 在匿名函数外部定义变量
int a=100, b=200, c=300;
// 调用匿名函数
[](){
    // 打印外部变量的值
    qDebug() << "a:" << a << ", b: " << b << ", c:" << c;  // error, 不能使用任何外部变量
}

[&](){
    qDebug() << "hello, 我是一个lambda表达式...";
    qDebug() << "使用引用的方式传递数据: ";
    qDebug() << "a+1:" << a++ << ", b+c= " << b+c;
}();

// 值拷贝的方式使用外部数据
[=](int m, int n)mutable{
    qDebug() << "hello, 我是一个lambda表达式...";
    qDebug() << "使用拷贝的方式传递数据: ";
    // 拷贝的外部数据在函数体内部是只读的, 如果不添加 mutable 关键字是不能修改这些只读数据的值的
    // 添加 mutable 允许修改的数据是拷贝到函数内部的副本, 对外部数据没有影响
    qDebug() << "a+1:" << a++ << ", b+c= " << b+c;
    qDebug() << "m+1: " << ++m << ", n: " << n;
}(1, 2);

总结:文章中主要介绍了Qt中的信号槽, 主要内容包括: 信号槽的拓展Lambda表达式。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小梁今天敲代码了吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值