一.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());
});
}