QT定时器:QObject&QTimer解析

发布于:2025-07-05 ⋅ 阅读:(15) ⋅ 点赞:(0)

一.QObject 定时器:基于事件机制

在QObject类中内置了定时器的功能,可以通过重写timerEvent()时间处理函数实现定时任务 ,这种事Qt中定时器的底层实现。
核心原理:

  • 使用startTimer(int mesc) 启动定时器 返回定时器的唯一ID
  • 当定时时间到达时,Qt 会向对象发送 timerEvent() 事件,需重写该函数处理。
  • 通过 killTimer(timerId) 停止指定定时器。

示例代码:通过定时器实现简单的图片轮播

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    virtual void timerEvent(QTimerEvent* event);

private slots:
    void on_starttime_clicked();

    void on_timeout_clicked();

private:
    Ui::Widget *ui;
    int timeID;
    int picID;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    picID = 2;
    QPixmap pixmap("D:\\Desktop\\Musicplayer\\images\\rec\\001.png");
    ui->label->setPixmap(pixmap);
}

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

void Widget::timerEvent(QTimerEvent *event)
{
    if(timeID != event->timerId())
        return ;

    //QString fileName = QString("%1.png").arg(picID, 3, 10, QChar('0'));
    QString fileName = QString("%1").arg(picID, 3, 10, QChar('0'));
    
    QString path = "D:\\Desktop\\Musicplayer\\images\\rec\\" + fileName;
    qDebug()<<path;
    ui->label->setPixmap(path);

    picID++;
    if(41 == picID)
        picID = 1;
}


void Widget::on_starttime_clicked()
{
    //返回定时器编号
    timeID = this->startTimer(1000);
}

void Widget::on_timeout_clicked()
{
    this->killTimer(timeID);
}

最终就可以通过开始和暂停两个按钮控制图片的轮播:
在这里插入图片描述
优缺点:

  • 轻量级,无需创建额外对象,直接基于 QObject 事件机制。
  • 适合简单的单次或周期性任务,代码结构紧凑。
  • 功能单一,仅支持定时事件,无信号槽机制。
  • 多个定时器需通过 ID 区分。

二.QTimer:封装的定时器类

QTimer则是Qt中对定时器进行了一次封装,提供了更灵活的信号与槽方式,是比较常用的方案。
核心特性:

  • 通过 timeout() 信号连接自定义槽函数,替代事件重写。
  • setSingleShot(true) 可设置单次触发模式。
  • QTimer::singleShot(msec, functor) 用于快速实现单次延迟任务。

同样示例一个图片轮播功能:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>
#include <memory>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_starttime_clicked();
    void on_timeout_picID();

    void on_onlyone_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    std::unique_ptr<QTimer> timer;
    int picID;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ,timer(std::make_unique<QTimer>(this))
{
    ui->setupUi(this);   
    QImage image("D:\\Desktop\\Musicplayer\\images\\rec\\001.png");
    ui->label->setPixmap(QPixmap::fromImage(image));
    picID = 2;

    connect(timer.get(),&QTimer::timeout,this,&Widget::on_timeout_picID);

}

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


void Widget::on_starttime_clicked()
{
    timer->start(1000);
}

void Widget::on_timeout_picID()
{
    QString fileName = QString("%1").arg(picID, 3, 10, QChar('0'));

    QString path = "D:\\Desktop\\Musicplayer\\images\\rec\\" + fileName;

    ui->label->setPixmap(QPixmap::fromImage(QImage(path)));
    picID++;
    if(41==picID)
        picID = 1;

}

void Widget::on_onlyone_clicked()
{
    timer->stop();
}

void Widget::on_pushButton_2_clicked()
{
    QTimer::singleShot(1000,this,&Widget::on_timeout_picID);
}

在这里插入图片描述
其中单次可以让图片只轮播一次。
QTimer特点:

  • 基于信号与槽机制实现。
  • 封装度高 接口简单。
  • 支持单次循环触发、信号连接、静态函数等。
  • 推荐在业务逻辑 动画 复杂定时控制中使用。

定时器注意事项:

  • 使用智能指针管理 QTimer 对象,避免内存泄漏。若 QTimer 的父对象已设置(如 this),则无需手动释放。
  • QTimer 的 singleShot 可在任意线程调用,但槽函数执行于接收者所在线程。

三.QTimer::singleShot 的灵活使用

QTimer::singleShot 是一个非常实用的静态函数,用于实现 “延迟执行一次任务”,无需手动管理定时器生命周期:

// 场景1:延迟显示提示信息
void Widget::showTempMessage(const QString &msg)
{
    ui->statusLabel->setText(msg);
    QTimer::singleShot(3000, [this]() {  // 3秒后清除消息
        ui->statusLabel->clear();
    });
}

// 场景2:模拟网络请求回调
void Widget::fetchDataAsync()
{
    // 显示加载状态
    ui->progressBar->setVisible(true);
    
    // 模拟2秒后返回数据(实际项目中替换为真实网络请求)
    QTimer::singleShot(2000, [this]() {
        ui->progressBar->setVisible(false);
        emit dataFetched(generateFakeData());
    });
}

网站公告

今日签到

点亮在社区的每一天
去签到