QT定时器与lambda表达式联合使用

QTimer定时器在程序开发中经常使用,比如网络请求超时检查,定时刷新数据,控制动态图开始停止等功能,一般如果是定时触发某个标志,用专来的槽函数处理会显示有点繁琐,如果用lambda表达式处理就不用专门声明定义槽函数,这样代码会更简洁。下面是QTimer与labmda表达式的结合使用。

1.先看下lambda表达式的基本定义和使用

lambda表达式定义
[捕获列表]    (参数列表)         返回类型    {函数体}
[capture list](parameter list)->return type {function body}
其中,捕获列表是一个lambda所在函数中定义的局部变量的列表(通常为空);return type,parameter list和function body与任何普通函数一样,分别表示返回类型,参数列表和函数体。但是,与普通函数不同,lambda必须使用尾置返回来指定返回类型。

    《Primer C++》(第5版)6.3.3节 使用尾置返回类型
    //func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
    auto func(int i)->int(*)[10];

我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
auto f = [] {return 52}
定义一个可调用对象f,它不接受参数,返回52
cout << f() << endl;//打印52
在lambda中忽略括号和参数列表等价于指定一个空参数列表。在此例中,当调用f时,参数列表是空的。
如果忽略返回类型,lambda根据函数体中的代码推断出返回类型。如果函数体只是一个return语句,则返回从返回的表达式的类型推断而来,否则,返回类型为void.

捕获列表可以有多个捕获选项,以逗号分隔,规则如下:
[ ]        :无捕获,函数体内不能访问任何外部变量
[ =]       :以值(拷贝)的方式捕获所有外部变量,函数体内可以访问,但是不能修改。
[ &]       :以引用的方式捕获所有外部变量,函数体内可以访问并修改(需要当心无效的引用);
[ var]     :以值(拷贝)的方式捕获某个外部变量,函数体可以访问但不能修改。
[ &var]    :以引用的方式获取某个外部变量,函数体可以访问并修改
[ this]    :捕获this指针,可以访问类的成员变量和函数,
[ =,&var] :引用捕获变量var,其他外部变量使用值捕获。
[ &,var]  :只捕获变量var,其他外部变量使用引用捕获。
 

示例:

#include "mainwindow.h"

#include <QApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    int x = 15;
    int y = 19;
    auto f = []{return 22;};//花括号后面一定要加分号
    auto f1 = [=](){return x;};//以值方式捕获所有变量,不能修改
    auto f2 = [&](){return ++x;};//以引用方式捕获所有变量,可以修改,但要当心引用无效
    auto f3 = [x](){return x;};//以值 方式捕获x,不能修改值
    auto f4 = [x, &y](){y += x; return y;};//以值 方式捕获x,以引用方式捕获y,y可以修改
    auto f5 = [&, y](){x += y; return x;};//以引用方式捕获y之外的所有变量,y不能修改
    auto f6 = [&](){y += ++x; return y;};//以引用方式捕获所有变量,可以修改
    //auto f7 = [](){return x;};//无捕获,不能使用外部变量,编译错误

    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f1() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f2() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f3() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f4() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f5() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << f6() << endl;
    qDebug() << "x = " << x << "  y = " << y << endl;
    qDebug() << "Hello World!" << endl;

    MainWindow w;
    w.show();
    return a.exec();
}

运行结果:

 2.QTimer定时器的使用:

2.1 定时器模拟5秒钟下载完成,gif动画停止

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class QMovie;

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

public slots:
    void slotDownload();

    void slotDownloadFinished();

private:
    Ui::MainWindow *ui;
    QMovie *m_pMovie;
    QTimer *m_pTimer;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <QMovie>
#include <QDebug>
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_pMovie(new QMovie(":/downloading_80.gif"))
    , m_pTimer(new QTimer(this))
{
    ui->setupUi(this);
    ui->label_gif->setMovie(m_pMovie);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(slotDownload()));
    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(slotDownloadFinished()));
}

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

void MainWindow::slotDownload()
{
    qDebug() << "MainWindow::slotDownload=======start===============" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    m_pMovie->start();
    m_pTimer->start(5000);
}

void MainWindow::slotDownloadFinished()
{
    qDebug() << "MainWindow::slotDownloadFinished===================" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    m_pMovie->stop();
    m_pTimer->stop();
}

点击下载按钮后,5秒到时动画停止

这种是循环的,必须把定时器关掉才会停止定时器。

2.2下面这种是单次触发

void MainWindow::slotDownload()
{
    m_pMovie->start();
    qDebug() << "MainWindow::slotDownload=====start====singleShot===" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    QTimer::singleShot(5000, this, SLOT(slotDownloadFinished()));
}

void MainWindow::slotDownloadFinished()
{
    qDebug() << "MainWindow::slotDownloadFinished===================" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    m_pMovie->stop();
}

2.3 使用lambda表达式形式

void MainWindow::slotDownload()
{
    m_pMovie->start();
   
    qDebug() << "MainWindow::slotDownload=====start====singleShot===" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");

    QTimer::singleShot(5000,[this](){ //5秒钟还没下完就先停止动画
        m_pMovie->stop();
        qDebug() << "MainWindow::slotDownload==end======singleShot======" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    });

}

运行结果:

 4.也可以由QTimer控件是否使用单次

void MainWindow::slotDownload()
{
    m_pMovie->start();
    qDebug() << "MainWindow::slotDownload=====start====singleShot===" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");

    QTimer *tim = new QTimer(this);
    tim->setSingleShot(true);
    connect(tim, &QTimer::timeout, this, [tim, this] {
        qDebug() << "MainWindow::slotDownload==end======singleShot======" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
        m_pMovie->stop();
        tim->deleteLater();
    });
    tim->start(5000);
}

运行结果:

 从以上可以看出,使用lambda表达式,代码会更简洁。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值