副标题:深入Qt时间日期内核、QTimer源码实现与高精度定时器的性能优化实战
摘要
Qt框架提供了完整的时间日期处理能力和灵活的定时器机制。本文将深入解析Qt时间日期类的架构设计、QTimer的源码实现原理,以及如何在跨平台环境下实现高精度定时器,涵盖从毫秒级精度到微秒级定时器的完整技术方案。
第一章:Qt时间日期体系架构设计
1.1 核心类层次结构
Qt的时间日期系统由以下几个核心类组成:
QDate → 日期处理(年/月/日)
QTime → 时间处理(时/分/秒/毫秒)
QDateTime → 日期时间组合
QTimeZone → 时区处理(Qt 5.2+)
QDeadlineTimer → 截止时间计时器(Qt 5.8+)
类关系图:
cpp
// QDateTime 组合了 QDate 和 QTime
class QDateTime {
private:
QDate date;
QTime time;
QTimeZone timeZone; // Qt 5.2+
};
1.2 QDate源码解析
源码路径 :qtbase/src/corelib/time/qdate.cpp
QDate内部使用Julian Day(儒略日)存储日期,这是一种连续计数天数系统,便于日期计算。
cpp
// qdate.cpp - 核心数据结构
class QDate {
private:
int jd; // Julian Day编号
// 静态成员:空日期和最大/最小日期
static constexpr int nullJd = std::numeric_limits<int>::min();
static constexpr int minJd = -784350574879; // 约公元前2亿年
static constexpr int maxJd = 784354017364; // 约公元2亿年
};
日期验证算法(简化版):
cpp
bool QDate::isValid(int year, int month, int day)
{
// 快速范围检查
if (year < 1752 || month < 1 || month > 12 || day < 1 || day > 31)
return false;
// 月份天数表(考虑闰年)
static const int daysInMonth[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int maxDay = daysInMonth[month - 1];
// 闰年二月处理
if (month == 2 && isLeapYear(year))
maxDay = 29;
return day <= maxDay;
}
// 闰年判断(格里高利历规则)
bool QDate::isLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
Julian Day转换算法:
cpp
// 从年/月/日到Julian Day的转换(简化版)
int QDate::gregorianToJulian(int year, int month, int day)
{
// 使用简化的转换公式
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
return day + (153 * m + 2) / 5 + 365 * y
+ y / 4 - y / 100 + y / 400 - 32045;
}
1.3 QTime源码解析
源码路径 :qtbase/src/corelib/time/qtime.cpp
QTime内部存储从午夜开始的毫秒数(milliseconds since midnight)。
cpp
class QTime {
private:
int mds; // Milliseconds since midnight (0-86399999)
public:
// 构造函数
QTime() : mds(NullTime) {}
QTime(int h, int m, int s = 0, int ms = 0)
{
setHMS(h, m, s, ms);
}
bool setHMS(int h, int m, int s, int ms)
{
if (!isValid(h, m, s, ms)) {
mds = NullTime;
return false;
}
mds = (h * 3600 + m * 60 + s) * 1000 + ms;
return true;
}
// 时间计算
QTime addMSecs(int ms) const
{
QTime t;
if (mds == NullTime)
return t;
t.mds = (mds + ms) % 86400000; // 取模24小时
if (t.mds < 0)
t.mds += 86400000;
return t;
}
};
1.4 QDateTime的时区处理
源码路径 :qtbase/src/corelib/time/qdatetime.cpp
QDateTime支持三种时间规范(TimeSpec):
Qt::LocalTime- 本地时间Qt::UTC- 协调世界时Qt::OffsetFromUTC- 固定偏移量Qt::TimeZone- 时区(需要QTimeZone)
cpp
// QDateTime私有数据结构
class QDateTimePrivate {
public:
QDate date;
QTime time;
Qt::TimeSpec spec;
int offsetFromUtc; // 仅当spec=OffsetFromUTC时有效
QTimeZone timeZone; // 仅当spec=TimeZone时有效
// 转换为UTC内部存储
void toUtc()
{
if (spec == Qt::LocalTime) {
// 使用系统API获取偏移量
offsetFromUtc = systemOffset(date, time);
spec = Qt::OffsetFromUTC;
}
if (spec == Qt::OffsetFromUTC) {
// 应用偏移量
QTime utcTime = time.addSecs(-offsetFromUtc);
// ... 处理日期变更
spec = Qt::UTC;
}
}
};
第二章:QTimer定时器机制深度解析
2.1 QTimer架构设计
源码路径 :qtbase/src/corelib/kernel/qtimer.cpp 和 qtbase/src/corelib/kernel/qobject.cpp
QTimer是基于QObject的事件驱动定时器,依赖于事件循环。
cpp
class QTimer : public QObject
{
Q_OBJECT
Q_PROPERTY(int interval READ interval WRITE setInterval)
Q_PROPERTY(bool singleShot READ singleShot WRITE setSingleShot)
Q_PROPERTY(bool active READ isActive)
public:
QTimer(QObject *parent = nullptr);
~QTimer();
int interval() const { return d_func()->interval; }
bool isActive() const;
bool isSingleShot() const;
public Q_SLOTS:
void start(int msec) { setInterval(msec); start(); }
void start();
void stop();
void setInterval(int msec);
void setSingleShot(bool singleShot);
void setTimerType(Qt::TimerType type);
Q_SIGNALS:
void timeout(QPrivateSignal);
protected:
void timerEvent(QTimerEvent *event) override;
};
2.2 QTimer的底层实现
定时器ID管理:
cpp
// QTimer私有数据
class QTimerPrivate : public QObjectPrivate
{
public:
int interval;
int timerId;
Qt::TimerType timerType;
bool singleShot : 1;
bool active : 1;
// 静态ID池管理
static QBasicAtomicInt idCounter;
static int allocateId()
{
return idCounter.fetchAndAddRelaxed(1) + 1;
}
};
start()方法实现:
cpp
void QTimer::start()
{
Q_D(QTimer);
if (d->interval < 0) {
qWarning("QTimer::start: interval < 0");
return;
}
// 如果已激活,先停止
if (d->timerId != 0)
stop();
// 向事件循环注册定时器
d->timerId = QObject::startTimer(d->interval, d->timerType);
d->active = (d->timerId != 0);
if (!d->active)
qWarning("QTimer::start: failed to start timer");
}
关键 :QTimer不直接管理定时器,而是调用QObject::startTimer(),后者向QAbstractEventDispatcher注册定时器。
2.3 Qt定时器类型(Qt::TimerType)
Qt提供三种定时器精度类型:
cpp
enum TimerType {
PreciseTimer, // 精确定时器(尽量保持精度)
CoarseTimer, // 粗精度定时器(允许±5%误差,默认)
VeryCoarseTimer // 极粗精度(仅保证分钟级精度)
};
不同平台的实现差异:
Windows平台(Win32 API)
cpp
// qtbase/src/corelib/kernel/qeventdispatcher_win.cpp
void QEventDispatcherWIN32::registerTimer(int timerId, int interval,
Qt::TimerType timerType, QObject *obj)
{
// Windows多媒体定时器
if (timerType == Qt::PreciseTimer && interval < 100) {
// 使用timeSetEvent()(高精度)
MMRESULT result = timeSetEvent(interval, 1, callback, ...);
} else {
// 使用SetTimer()(普通精度)
UINT_PTR id = SetTimer(NULL, timerId, interval, NULL);
}
}
Linux平台(glib/eventfd)
cpp
// qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp
void QEventDispatcherGLib::registerTimer(int timerId, int interval,
Qt::TimerType timerType, QObject *obj)
{
// 使用timerfd_create()(Linux内核高精度定时器)
if (timerType == Qt::PreciseTimer) {
int fd = timerfd_create(CLOCK_MONOTONIC, 0);
// 设置定时器间隔
struct itimerspec spec;
spec.it_interval.tv_nsec = interval * 1000000; // 转换为纳秒
timerfd_settime(fd, 0, &spec, NULL);
} else {
// 使用glib的g_timeout_add()
g_timeout_add(interval, callback, data);
}
}
2.4 QTimer精度问题分析
问题:QTimer的精度受限于:
- 操作系统调度精度(Windows默认15.6ms,Linux默认4ms)
- 事件循环负载(如果事件循环繁忙,定时器会延迟)
- 定时器类型(CoarseTimer允许±5%误差)
实测数据(Windows 10,Intel i7):
设置间隔: 1ms → 实际间隔: 15.6ms (系统时钟粒度)
设置间隔: 10ms → 实际间隔: 15.6ms
设置间隔: 16ms → 实际间隔: 15.6ms
设置间隔: 20ms → 实际间隔: 31.2ms
设置间隔: 100ms → 实际间隔: 100±5ms (CoarseTimer)
优化方案:
cpp
// 方案1:使用Qt::PreciseTimer
QTimer *timer = new QTimer(this);
timer->setTimerType(Qt::PreciseTimer);
timer->start(1); // 尝试1ms精度
// 方案2:调整系统时钟粒度(Windows)
#include <windows.h>
timeBeginPeriod(1); // 设置最小时钟粒度为1ms
// ... 使用QTimer
timeEndPeriod(1); // 恢复
// 方案3:使用QElapsedTimer进行忙等待(高精度)
QElapsedTimer elapsed;
elapsed.start();
while (elapsed.nsecsElapsed() < 1000000) { // 1ms
// 忙等待(占用CPU)
}
第三章:高精度定时器实现方案
3.1 QElapsedTimer源码解析
源码路径 :qtbase/src/corelib/time/qelapsedtimer.cpp
QElapsedTimer用于测量经过的时间,而不是定时触发。
cpp
class QElapsedTimer
{
public:
// 启动计时器
void start() { t1 = currentClockTime(); }
// 返回经过的毫秒数
qint64 elapsed() const
{
return currentClockTime() - t1;
}
// 返回经过的纳秒数(Qt 5.8+)
qint64 nsecsElapsed() const
{
return (currentClockTime() - t1) * 1000000;
}
// 判断是否超时
bool hasExpired(qint64 timeout) const
{
return elapsed() > timeout;
}
private:
qint64 t1; // 起始时间戳
// 平台相关的时钟源
static qint64 currentClockTime()
{
#ifdef Q_OS_WIN
// Windows: 使用QueryPerformanceCounter()
LARGE_INTEGER freq, counter;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&counter);
return (counter.QuadPart * 1000000000) / freq.QuadPart;
#elif defined(Q_OS_LINUX)
// Linux: 使用clock_gettime(CLOCK_MONOTONIC)
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000000 + ts.tv_nsec;
#endif
}
};
3.2 高精度定时器实现(微秒级)
方案:QElapsedTimer + 忙等待(适用于<10ms的短间隔)
cpp
#include <QElapsedTimer>
#include <QThread>
class HighPrecisionTimer : public QThread
{
Q_OBJECT
public:
HighPrecisionTimer(QObject *parent = nullptr)
: QThread(parent), m_intervalUs(1000) {} // 默认1ms
void setIntervalUs(qint64 interval) { m_intervalUs = interval; }
void run() override
{
QElapsedTimer timer;
while (!isInterruptionRequested()) {
timer.start();
// 执行定时任务
emit timeout();
// 计算剩余时间并等待
qint64 elapsed = timer.nsecsElapsed() / 1000; // 转换为微秒
qint64 remaining = m_intervalUs - elapsed;
if (remaining > 0) {
// 微秒级忙等待(QThread::usleep精度不够)
busyWaitUs(remaining);
}
}
}
signals:
void timeout();
private:
void busyWaitUs(qint64 us)
{
QElapsedTimer t;
t.start();
while (t.nsecsElapsed() / 1000 < us) {
// 忙等待(占用CPU核心)
// 可在循环中加入QThread::yieldCurrentThread()
}
}
qint64 m_intervalUs;
};
注意:忙等待会占用CPU核心,仅适用于短期高精度定时。
3.3 使用C++11 chrono实现跨平台高精度定时器
cpp
#include <chrono>
#include <thread>
#include <functional>
class ChronoHighPrecisionTimer
{
public:
using Callback = std::function<void()>;
ChronoHighPrecisionTimer(int intervalUs, Callback cb)
: m_intervalUs(intervalUs), m_callback(cb), m_running(false) {}
void start()
{
m_running = true;
m_thread = std::thread([this]() {
auto nextTime = std::chrono::steady_clock::now();
while (m_running) {
nextTime += std::chrono::microseconds(m_intervalUs);
// 执行回调
if (m_callback) {
m_callback();
}
// 精确睡眠到下一个时间点
std::this_thread::sleep_until(nextTime);
}
});
}
void stop()
{
m_running = false;
if (m_thread.joinable())
m_thread.join();
}
private:
int m_intervalUs;
Callback m_callback;
std::thread m_thread;
std::atomic<bool> m_running;
};
// 使用示例
ChronoHighPrecisionTimer timer(1000, []() {
qDebug() << "High precision timer triggered:"
<< QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
});
timer.start();
第四章:实战应用案例
4.1 案例1:实时数据采样系统(1ms采样率)
需求:从传感器以1ms间隔采样数据,要求高精度定时。
实现方案:
cpp
#include <QObject>
#include <QTimer>
#include <QVector>
#include <QElapsedTimer>
class DataSampler : public QObject
{
Q_OBJECT
public:
DataSampler(QObject *parent = nullptr)
: QObject(parent), m_sampleCount(0)
{
// 方案1:QTimer(精度不够1ms)
// m_timer = new QTimer(this);
// m_timer->setTimerType(Qt::PreciseTimer);
// connect(m_timer, &QTimer::timeout, this, &DataSampler::sample);
// m_timer->start(1);
// 方案2:高精度定时器线程
m_highPrecisionTimer = new HighPrecisionTimer(this);
connect(m_highPrecisionTimer, &HighPrecisionTimer::timeout,
this, &DataSampler::sample);
m_highPrecisionTimer->setIntervalUs(1000); // 1ms
m_highPrecisionTimer->start();
}
void sample()
{
// 采样传感器数据
double value = readSensor();
// 记录时间戳
QDateTime timestamp = QDateTime::currentDateTime();
// 存储数据
m_data.append({timestamp, value});
m_sampleCount++;
// 每1000个样本输出一次统计
if (m_sampleCount % 1000 == 0) {
qDebug() << "Sampled" << m_sampleCount << "points";
qDebug() << "Last sample:" << value << "at"
<< timestamp.toString("hh:mm:ss.zzz");
}
}
QVector<QPair<QDateTime, double>> getData() const { return m_data; }
private:
double readSensor() {
// 模拟传感器读取
return QRandomGenerator::global()->generateDouble() * 100.0;
}
// QTimer *m_timer; // 精度不够
HighPrecisionTimer *m_highPrecisionTimer;
QVector<QPair<QDateTime, double>> m_data;
int m_sampleCount;
};
4.2 案例2:动画时间轴控制(60FPS)
需求:实现平滑的60FPS动画,使用QTimer控制帧率。
cpp
#include <QTimer>
#include <QElapsedTimer>
#include <QPainter>
#include <QWidget>
class AnimationWidget : public QWidget
{
Q_OBJECT
public:
AnimationWidget(QWidget *parent = nullptr)
: QWidget(parent), m_angle(0.0), m_fps(60)
{
// 计算帧间隔(16.67ms for 60FPS)
int frameInterval = 1000 / m_fps;
m_timer = new QTimer(this);
m_timer->setTimerType(Qt::PreciseTimer);
connect(m_timer, &QTimer::timeout, this, &AnimationWidget::updateAnimation);
m_timer->start(frameInterval);
// 性能监控
m_fpsTimer.start();
m_frameCount = 0;
}
void paintEvent(QPaintEvent *event) override
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制旋转矩形
painter.translate(width() / 2, height() / 2);
painter.rotate(m_angle);
painter.fillRect(-50, -50, 100, 100, Qt::blue);
// 显示FPS
painter.resetTransform();
painter.drawText(10, 20, QString("FPS: %1").arg(calculateFps()));
}
private slots:
void updateAnimation()
{
m_angle += 1.0; // 每帧旋转1度
if (m_angle >= 360.0)
m_angle = 0.0;
update(); // 触发重绘
}
double calculateFps()
{
m_frameCount++;
qint64 elapsed = m_fpsTimer.elapsed();
if (elapsed >= 1000) { // 每秒计算一次
double fps = m_frameCount * 1000.0 / elapsed;
m_frameCount = 0;
m_fpsTimer.start();
return fps;
}
return 0.0;
}
private:
QTimer *m_timer;
double m_angle;
int m_fps;
QElapsedTimer m_fpsTimer;
int m_frameCount;
};
4.3 案例3:定时任务调度器(类似cron)
需求:实现灵活的定时任务调度,支持:
- 固定间隔执行
- 指定时间执行
- 延迟执行
cpp
#include <QObject>
#include <QTimer>
#include <QDateTime>
#include <QMap>
#include <functional>
class TaskScheduler : public QObject
{
Q_OBJECT
public:
using Task = std::function<void()>;
TaskScheduler(QObject *parent = nullptr) : QObject(parent) {}
// 注册固定间隔任务
void scheduleInterval(const QString &taskId, int intervalMs, Task task)
{
QTimer *timer = new QTimer(this);
timer->setInterval(intervalMs);
timer->setSingleShot(false);
connect(timer, &QTimer::timeout, task);
timer->start();
m_timers[taskId] = timer;
}
// 注册一次性延迟任务
void scheduleDelay(const QString &taskId, int delayMs, Task task)
{
QTimer *timer = new QTimer(this);
timer->setInterval(delayMs);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [task, timer]() {
task();
timer->deleteLater();
});
timer->start();
}
// 注册指定时间执行任务
void scheduleAt(const QString &taskId, const QDateTime &targetTime, Task task)
{
QDateTime now = QDateTime::currentDateTime();
qint64 delayMs = now.msecsTo(targetTime);
if (delayMs < 0) {
qWarning() << "Target time is in the past:" << targetTime;
return;
}
scheduleDelay(taskId, delayMs, task);
}
// 取消任务
void cancel(const QString &taskId)
{
if (m_timers.contains(taskId)) {
m_timers[taskId]->stop();
m_timers[taskId]->deleteLater();
m_timers.remove(taskId);
}
}
private:
QMap<QString, QTimer*> m_timers;
};
// 使用示例
TaskScheduler scheduler;
// 每5秒执行一次
scheduler.scheduleInterval("heartbeat", 5000, []() {
qDebug() << "Heartbeat at:" << QDateTime::currentDateTime();
});
// 10秒后执行一次
scheduler.scheduleDelay("delayed_task", 10000, []() {
qDebug() << "Delayed task executed!";
});
// 明天上午9点执行
QDateTime targetTime(QDate::currentDate().addDays(1), QTime(9, 0, 0));
scheduler.scheduleAt("morning_task", targetTime, []() {
qDebug() << "Good morning! Task executed at 9 AM.";
});
第五章:性能优化与最佳实践
5.1 QTimer性能优化技巧
技巧1:使用QBasicTimer减少内存分配
cpp
// 低效方式:频繁创建/销毁QTimer
for (int i = 0; i < 1000; ++i) {
QTimer *timer = new QTimer(this);
timer->start(100);
// ...
delete timer; // 开销大
}
// 高效方式:使用QBasicTimer
class MyObject : public QObject
{
public:
void startTimer(int interval) {
m_timer.start(interval, this);
}
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == m_timer.timerId()) {
// 处理定时器事件
}
}
private:
QBasicTimer m_timer; // 轻量级,不继承QObject
};
技巧2:批量处理定时器事件
cpp
// 低效:每个定时器独立处理
QTimer *timer1 = new QTimer;
QTimer *timer2 = new QTimer;
connect(timer1, &QTimer::timeout, []() { process1(); });
connect(timer2, &QTimer::timeout, []() { process2(); });
// 高效:合并到同一个定时器
QTimer *masterTimer = new QTimer;
masterTimer->setInterval(100);
connect(masterTimer, &QTimer::timeout, []() {
process1();
process2();
process3();
});
技巧3:使用Qt::CoarseTimer降低系统负担
cpp
// 对精度要求不高的定时器使用CoarseTimer
QTimer *timer = new QTimer;
timer->setTimerType(Qt::CoarseTimer); // 允许±5%误差
timer->start(1000); // 1秒间隔,实际可能在950-1050ms之间
5.2 跨平台兼容性处理
问题:不同操作系统定时器精度差异大。
解决方案:运行时检测并适配。
cpp
#include <QSysInfo>
#include <QOperatingSystemVersion>
class AdaptiveTimer : public QTimer
{
public:
AdaptiveTimer(QObject *parent = nullptr) : QTimer(parent)
{
// 根据平台调整定时器类型
detectPlatformAndAdjust();
}
void setAdaptiveInterval(int intervalMs)
{
m_requestedInterval = intervalMs;
// Windows系统时钟粒度问题
#ifdef Q_OS_WIN
if (intervalMs < 16) {
// 尝试设置系统时钟粒度为1ms
timeBeginPeriod(1);
setTimerType(Qt::PreciseTimer);
}
#endif
setInterval(intervalMs);
}
private:
void detectPlatformAndAdjust()
{
#ifdef Q_OS_WIN
// Windows: 检查是否为Win10 2004+(支持更高精度)
if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 19041)) {
// Win10 2004+ 支持更高精度
qDebug() << "Windows 10 2004+ detected, high precision available";
}
#elif defined(Q_OS_LINUX)
// Linux: 检查是否有timerfd支持
int fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (fd >= 0) {
qDebug() << "Linux timerfd available";
close(fd);
}
#endif
}
int m_requestedInterval;
};
5.3 内存泄漏防范
常见陷阱:QTimer在析构时不会自动停止。
cpp
// 错误示例:内存泄漏
void MyClass::startTimer()
{
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, []() {
// 如果this被析构,timer会成为野指针
});
timer->start(1000);
}
// 正确做法1:父子关系自动管理
QTimer *timer = new QTimer(this); // this析构时自动删除timer
// 正确做法2:手动管理
QTimer *timer = new QTimer;
connect(timer, &QTimer::timeout, this, &MyClass::handleTimeout);
connect(timer, &QTimer::destroyed, []() {
qDebug() << "Timer destroyed";
});
timer->start(1000);
// 在析构函数中
MyClass::~MyClass()
{
if (timer) {
timer->stop();
delete timer;
}
}
第六章:高级话题与扩展
6.1 QDeadlineTimer的使用(Qt 5.8+)
QDeadlineTimer提供了一种基于截止时间的定时器,适用于超时控制。
cpp
#include <QDeadlineTimer>
#include <QNetworkReply>
void fetchWithTimeout(const QUrl &url, int timeoutMs)
{
QNetworkAccessManager manager;
QNetworkReply *reply = manager.get(QNetworkRequest(url));
// 设置截止时间
QDeadlineTimer deadline(timeoutMs, Qt::PreciseTimer);
// 等待回复,带超时
while (reply->isRunning()) {
if (deadline.hasExpired()) {
qWarning() << "Request timeout!";
reply->abort();
return;
}
QCoreApplication::processEvents(); // 处理事件循环
}
// 处理回复
QByteArray data = reply->readAll();
qDebug() << "Received" << data.size() << "bytes";
reply->deleteLater();
}
6.2 使用Qt Concurrent实现定时任务
cpp
#include <QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>
void scheduleConcurrentTask(int intervalMs, std::function<void()> task)
{
// 在后台线程执行定时任务
QtConcurrent::run([intervalMs, task]() {
while (true) {
QThread::msleep(intervalMs);
task();
}
});
}
// 使用示例
scheduleConcurrentTask(1000, []() {
qDebug() << "Background task executed at:"
<< QDateTime::currentDateTime();
});
6.3 结合QStateMachine实现复杂定时逻辑
cpp
#include <QStateMachine>
#include <QTimer>
#include <QState>
class TimedStateMachine : public QObject
{
Q_OBJECT
public:
TimedStateMachine(QObject *parent = nullptr) : QObject(parent)
{
m_machine = new QStateMachine(this);
// 状态1:等待5秒
QState *state1 = new QState(m_machine);
QTimer *timer1 = new QTimer(state1);
timer1->setInterval(5000);
timer1->setSingleShot(true);
state1->assignProperty(timer1, "active", true);
connect(timer1, &QTimer::timeout, [this]() {
qDebug() << "State 1 timeout, switching to state 2";
});
// 状态2:等待10秒
QState *state2 = new QState(m_machine);
QTimer *timer2 = new QTimer(state2);
timer2->setInterval(10000);
timer2->setSingleShot(true);
state2->assignProperty(timer2, "active", true);
connect(timer2, &QTimer::timeout, [this]() {
qDebug() << "State 2 timeout, switching back to state 1";
});
// 状态转换
state1->addTransition(timer1, &QTimer::timeout, state2);
state2->addTransition(timer2, &QTimer::timeout, state1);
m_machine->setInitialState(state1);
m_machine->start();
}
private:
QStateMachine *m_machine;
};
总结
本文深入解析了Qt时间日期处理与QTimer定时器机制的完整技术栈,包括:
- QDate/QTime/QDateTime架构:Julian Day存储、时区处理、源码实现
- QTimer底层原理:事件驱动机制、跨平台实现差异、精度问题分析
- 高精度定时器方案:QElapsedTimer、忙等待、C++11 chrono
- 实战案例:实时数据采样、动画控制、任务调度器
- 性能优化:QBasicTimer、批量处理、平台适配
- 高级扩展:QDeadlineTimer、Qt Concurrent、状态机集成
关键要点:
- QTimer精度受操作系统限制,Windows默认15.6ms,Linux默认4ms
- 需要<10ms精度时,使用QElapsedTimer+忙等待或C++11 chrono
- 跨平台项目需要运行时检测并适配不同平台的定时器特性
- 使用QBasicTimer可以减少内存分配开销
- 及时停止和销毁QTimer,避免内存泄漏
《注:若有发现问题欢迎大家提出来纠正》
参考资料
- Qt官方文档:QTimer Class, QDateTime Class
- Qt源码:qtbase/src/corelib/time/, qtbase/src/corelib/kernel/qtimer.cpp
- 《Qt高级编程》 - 第8章 定时器与事件处理
- Microsoft Docs: Multimedia Timers (timeSetEvent)
- Linux man pages: timerfd_create(2), clock_gettime(3)
- C++ Standard: Library (C++11)