[QT编程系列-42]: QT定时器

目录

第1章 QT下的定时器

1.1 主要的对象

1.2 QTTimer定时的特点

1.3 QT高精度定时器QElapsedTimer: 计时

第2章 Windows操作系统下的高性能定时器

2.1 时钟分辨率

2.2 两种来实现高性能定时器:

2.3 timeSetEvent用法

第3章 timeSetEvent和QTimer比较

3.1 概述

3.2 精度比较


第1章 QT下的定时器

1.1 主要的对象

QT框架中提供了两种类型的定时器:QTimerQTimerEvent

  1. QTimer:QTimer是QT提供的一个高级定时器类,它基于QObject类,并且可以与事件循环一起工作。QTimer提供了灵活的定时器功能,可以执行单次或周期性的定时任务。

    使用QTimer,你可以执行以下操作:

    • 启动和停止定时器。
    • 设置定时器的间隔时间,即触发定时器事件的时间间隔。
    • 设置定时器的类型,包括单次执行和重复执行。
    • 与QObject的槽函数或lambda表达式连接,触发定时器事件时执行特定的操作。

    以下是使用QTimer的示例代码:

    QTimer *timer = new QTimer(this);
    
    // 设置定时器间隔时间
    timer->setInterval(1000); // 每隔1秒触发一次定时器事件
    
    // 连接定时器事件和槽函数
    // 定时器到期后,自动发送timeout信号
    connect(timer, &QTimer::timeout, this, &MyClass::handleTimerEvent);
    
    // 启动定时器
    timer->start();
    
  2. QTimerEvent:QTimerEvent是QT中的一个事件类,它用于处理与QTimer相关的事件。在继承了QObject的类中,可以重写QObject的虚函数timerEvent(QTimerEvent* event)来处理定时器事件。

    以下是使用QTimerEvent的示例代码:

    void MyClass::timerEvent(QTimerEvent *event)
    {
        if (event->timerId() == timerId) {
            // 处理定时器事件的逻辑
        }
        QObject::timerEvent(event);
    }
    

QTimer是较为常用和方便的定时器类,它提供了简单的接口和信号槽机制来处理定时器事件。而QTimerEvent则更加底层,需要手动重写timerEvent函数,并进行定时器事件的处理逻辑。开发者可以根据具体需求选择使用哪种定时器类型。

1.2 QTTimer定时的特点

QT定时器的特点如下:

  1. 简单易用:QT定时器提供了简洁、易于使用的接口,使开发人员可以轻松创建和管理定时器对象。

  2. 灵活性:QT定时器支持各种类型的定时器,包括单次定时器、重复定时器和单次重叠定时器,可以根据具体需求选择合适的类型。

  3. 高精度:QT定时器能够提供高精度的计时能力,通常以毫秒级别为单位。这样,开发人员可以实现精确的定时任务,满足应用程序的需求。QT定时器的最小精度是毫秒。

  4. 线程安全:QT定时器可以安全地在多线程环境中使用。它提供了线程安全的机制,使定时器能够在不同线程中创建、启动和停止,以满足多线程应用程序的需求

  5. 与信号槽机制集成:QT定时器可以与QT的信号槽机制无缝集成。开发人员可以将定时器的超时信号(timeout)与其他对象的槽函数或lambda表达式连接,实现灵活的定时任务逻辑。

  6. 多平台支持:QT定时器在不同平台的行为表现一致,无论是在Windows、MacOS、Linux等操作系统上,还是在嵌入式系统上。这保证了代码在不同平台下的可移植性和一致性。

  7. 高度集成:QT定时器可以与QT框架中的其他组件高度集成,如GUI控件、网络功能等。这使得开发人员可以将定时器与其他功能相结合,实现丰富的交互和功能。

综上所述,QT定时器具有简单易用、灵活性、高精度、线程安全、信号槽机制集成、多平台支持和高度集成等特点。它是QT开发中管理和执行定时任务的重要组件。无论是创建简单的定时器还是实现复杂的定时任务逻辑,QT定时器能够有效地满足开发人员的需求。

1.3 QT高精度定时器QElapsedTimer: 计时

QElapsedTimer主要用于衡量时间间隔,而不是作为实时定时器。它提供了对时间的高分辨率测量,但不具备定时器的触发和重复执行功能。

在QT中,针对高性能定时器需求,可以使用Qt的高分辨率定时器类QElapsedTimer。QElapsedTimer提供了纳秒级别的精确计时功能,适用于需要精确计时高性能定时的应用场景。

使用QElapsedTimer进行高性能定时,可以按照以下步骤:

  1. 创建和启动QElapsedTimer对象:

    QElapsedTimer timer;
    timer.start();
    
  2. 执行代码或任务:

    // 执行需要计时的代码或任务
    
  3. 获取经过的时间:

    qint64 elapsedTime = timer.nsecsElapsed();  // 获取经过的纳秒数
    
    // 转换为所需时间单位(如毫秒)
    qreal elapsedMilliseconds = static_cast<qreal>(elapsedTime) / 1000000.0;
    

示例代码:

#include <QCoreApplication>
#include <QElapsedTimer>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QElapsedTimer timer;
    timer.start();
    
    // 执行需要计时的代码或任务
    for (int i = 0; i < 10000000; ++i) {
        // 一些操作
    }
    
    qint64 elapsedTime = timer.nsecsElapsed();
    qreal elapsedMilliseconds = static_cast<qreal>(elapsedTime) / 1000000.0;
    qDebug() << "Elapsed time:" << elapsedMilliseconds << "ms";
    
    return a.exec();
}

使用QElapsedTimer类可以实现高性能的定时任务,尤其适用于需要测量代码执行时间或实现精确计时的应用程序。它提供了方便的接口来获取经过的纳秒数并进行单位转换,以满足不同精度的计时需求。

QElapsedTimer是Qt提供的一个高精度计时器类,用于测量时间间隔。它可以提供纳秒级别的精确计时,并且不受系统时间的影响。

以下是使用QElapsedTimer的示例代码:

#include <QCoreApplication>
#include <QElapsedTimer>
#include <QDebug>

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

    QElapsedTimer timer;
    timer.start();

    // 执行需要计时的代码或任务
    for (int i = 0; i < 10000000; ++i) {
        // 一些操作
    }

    qint64 elapsedTime = timer.nsecsElapsed();
    qreal elapsedMilliseconds = static_cast<qreal>(elapsedTime) / 1000000.0;
    qDebug() << "Elapsed time:" << elapsedMilliseconds << "ms";

    return a.exec();
}

在上面的示例中,创建了QElapsedTimer对象timer,并使用timer.start()开始计时。

然后,在需要计时的代码或任务执行之后,调用timer.nsecsElapsed()获取经过的纳秒数

如果需要将纳秒数转换为其他单位,可以使用除以适当的倍数来转换,例如将纳秒转换为毫秒,需要除以1000000。

最后,可以打印或使用获得的时间间隔进行后续处理。

请注意,QElapsedTimer的计时器受到系统的性能和精度限制,因此在不同的系统上可能会有所不同。但相对于Qt的QTimer类,QElapsedTimer提供了更高精度的测量能力,适用于需要准确计时的场景。

第2章 Windows操作系统下的高性能定时器

2.1 时钟分辨率

在Windows操作系统中,时钟分辨率是指操作系统提供的计时器的最小时间间隔。它决定了定时器的精度和能够设置的最小延迟时间。

Windows操作系统的默认时钟分辨率是15.6毫秒(ms),即0.0156秒。这意味着最小的延迟时间或定时器触发间隔是15.6毫秒。

然而,可以通过调用timeBeginPeriod函数来改变时钟分辨率。timeBeginPeriod函数允许应用程序请求更高的时钟精度。通常,较低的时钟分辨率会导致更高的系统资源消耗,因此应该根据实际需求进行权衡和使用。

请注意,更高的分辨率并不一定意味着更高的准确性。时钟分辨率受到系统硬件和操作系统调度的限制,并且实际的定时器触发时间可能会受到其他因素的影响,例如系统负载、其他进程的优先级、功耗管理等。

在使用时钟分辨率时,请考虑应用程序的需求和系统资源使用,并在必要时恢复默认的时钟分辨率。对于大多数通用应用程序而言,Windows默认的时钟分辨率已经足够使用。如有特定需求,可以使用高分辨率定时器等特定技术来获得更高的精确度和准确性。

2.2 两种来实现高性能定时器:

在Windows操作系统中,可以使用以下两种来实现高性能定时器:

  1. QueryPerformanceCounter QueryPerformanceFrequency 函数:=》计时
    这是Windows操作系统提供的API函数,用于获取高性能计数器的值和频率。高性能计数器提供了一个非常精确的计时方式,可以用来测量短时间间隔的性能。这是通过QueryPerformanceFrequency函数获取计时器的频率(每秒计时器的计数数目),然后使用QueryPerformanceCounter函数获取当前计时器的计数值。

    示例代码:

    LARGE_INTEGER frequency;
    LARGE_INTEGER start;
    LARGE_INTEGER end;
    
    QueryPerformanceFrequency(&frequency);
    QueryPerformanceCounter(&start);
    
    // 执行代码或任务
    
    QueryPerformanceCounter(&end);
    double elapsedTime = (end.QuadPart - start.QuadPart) * 1000.0 / frequency.QuadPart;
    

    使用QueryPerformanceCounter和QueryPerformanceFrequency函数可以获取非常高精度的时间戳,适用于实现精确计时和定时任务,尤其在需要测量代码执行时间或实现实时系统应用程序时。

  2. Multimedia Timers(多媒体定时器):定时
    Windows操作系统还提供了多媒体定时器API,以实现高分辨率低延迟的定时器功能。多媒体定时器允许以毫秒级的精度设置和触发定时器事件,适用于需要高性能定时器功能的多媒体应用程序和实时系统。

    这些API包括timeSetEvent、timeBeginPeriod和timeEndPeriod等函数。其中,timeSetEvent函数用于创建启动定时器,可以指定定时器的触发间隔、回调函数等参数。

    示例代码:

    void CALLBACK TimerCallback(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
    {
        // 定时器事件的处理逻辑
    }
    
    // 设置定时器并启动
    UINT timerId = timeSetEvent(
        period,            // 间隔时间(单位:毫秒)
        resolution,        // 分辨率(单位:毫秒)
        TimerCallback,     // 回调函数
        0,                 // 回调函数参数
        TIME_PERIODIC      // 定时器类型 - 重复执行
    );
    
    // 停止定时器
    timeKillEvent(timerId);
    

    使用多媒体定时器API可以实现高性能的毫秒级别定时器,适用于需要高精度的定时任务,并且对实时性要求较高的应用程序。

无论使用哪种方法,高性能定时器的准确性和精度受到多个因素的影响,包括硬件性能、系统负载等。在实际应用中,应根据实际需求和应用场景选择适合的方法,并进行充分的测试和验证,以确保定时器满足性能要求。

2.3 timeSetEvent用法

Windows API中的timeSetEvent函数用于设置定时器事件。

该函数允许您在指定的时间间隔内定期调用一个回调函数

以下是timeSetEvent函数的用法:

MMRESULT timeSetEvent(
    UINT           uDelay,
    UINT           uResolution,
    LPTIMECALLBACK lpTimeProc,
    DWORD_PTR      dwUser,
    UINT           fuEvent
);

参数说明:

  • uDelay:指定事件触发的延迟时间(以毫秒为单位)。
  • uResolution:指定定时器的最小时间分度。较小的值表示较高的分辨率。通常使用1作为最小分度。
  • lpTimeProc:指向回调函数的指针,当定时器事件触发时将调用该函数。
  • dwUser:用于传递给回调函数的用户定义的值(可选)。
  • fuEvent:事件类型标志,可以是TIME_ONESHOT(定时器只触发一次)或TIME_PERIODIC(定时器定期触发)。

使用示例:

#include <Windows.h>
#include <iostream>

void CALLBACK TimerProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    std::cout << "Timer event triggered!" << std::endl;
}

int main()
{
    // 设置一个定时器,每1000毫秒触发一次
    MMRESULT timerId = timeSetEvent(1000, 0, TimerProc, 0, TIME_PERIODIC);
    if (timerId == 0)
    {
        std::cout << "Failed to set timer!" << std::endl;
        return 1;
    }

    // 等待用户按下任意键停止定时器
    std::cout << "Timer started. Press any key to stop." << std::endl;
    std::cin.get();

    // 停止定时器
    MMRESULT result = timeKillEvent(timerId);
    if (result != TIMERR_NOERROR)
    {
        std::cout << "Failed to stop timer!" << std::endl;
        return 1;
    }

    std::cout << "Timer stopped." << std::endl;
    return 0;
}

上述示例代码中,我们创建了一个定时器,每1000毫秒触发一次。当定时器事件被触发时,回调函数TimerProc将被调用。用户可以通过按下任意键来停止定时器。

请注意,在使用timeSetEvent函数后,应使用timeKillEvent函数停止定时器。否则,定时器事件将会持续触发,可能导致不必要的问题。

第3章 timeSetEvent和QTimer比较

3.1 概述

timeSetEvent和QTimer是两个不同的定时器机制,分别对应于Windows平台的原生API和Qt框架中的定时器类。

  1. timeSetEvent:

    • timeSetEvent是Windows API提供的函数,用于设置定时器事件。
    • 它可以在指定的时间间隔内定期调用一个回调函数。
    • timeSetEvent需要手动设置参数,包括延迟时间、事件分辨率、回调函数等。
    • timeSetEvent是使用C/C++编程语言进行调用和使用。
  2. QTimer:

    • QTimer是Qt框架提供的定时器类,封装了定时器的常用操作。
    • 它基于事件循环机制,可以在Qt应用程序中使用。
    • QTimer提供了方便的接口和信号槽机制来处理定时器事件,无需手动设置回调函数。
    • QTimer提供了更高级别的功能,例如单次定时、间隔定时、暂停和重启等。

主要区别:

  • 实现方式不同:timeSetEvent是通过调用Windows API实现的,而QTimer是基于Qt框架提供的定时器类。
  • 参数设置:timeSetEvent需要手动设置参数,包括延迟时间、回调函数等,而QTimer受到Qt框架的封装,提供了更简单的接口和信号槽机制。
  • 平台依赖性:timeSetEvent是Windows特定的API,只能在Windows平台上使用。而QTimer是Qt框架的一部分,可以在跨平台的Qt应用程序中使用。

选择使用timeSetEvent还是QTimer取决于您的开发环境和需求。如果您正在使用Windows平台,并且更倾向于使用原生API和C/C++进行开发,则可以选择timeSetEvent。如果您使用Qt框架,并且希望使用更便捷的接口和信号槽机制,以及跨平台的可移植性,则可以选择QTimer。

3.2 精度比较

在精度方面,timeSetEvent和QTimer可能会有一些差异,具体取决于操作系统硬件的限制。

(1)timeSetEvent:

  • 精度依赖于操作系统提供的时钟分辨率,可以通过设置uResolution参数来控制,最小单位为毫秒。
  • Windows操作系统的时钟分辨率通常为15.6毫秒,即最小分辨率为15.6毫秒。
  • 由于存在系统调度和其他任务的影响,timeSetEvent的实际触发时间可能会有一定的偏差。

(2)QTimer:

  • QTimer基于操作系统和使用的定时器设备驱动,可以实现更高的精度。
  • 在大多数情况下,QTimer的默认精度为10毫秒,即最小分辨率为10毫秒。
  • Qt框架使用操作系统提供的定时器机制(例如Windows下使用Multimedia Timer或定时器线程)来实现定时器功能。
  • QTimer的精度还受到机器负载、操作系统调度和其他因素的影响。

需要注意的是,无论是timeSetEvent还是QTimer,它们都无法提供绝对精确的定时器,因为操作系统和硬件的限制会造成一定的延迟和偏差。如果需要更高精度的定时功能,可能需要使用特定于硬件的定时器库或使用专用硬件设备。

总而言之,对于一般应用场景,QTimer通常具有足够的精度,可以满足大多数需求。但如果对精度要求非常高,例如实时应用或需要更精确时间控制的场景,可能需要使用其他方案来满足需求。

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为了使更多的Qt初学者能尽快入门Qt,也为了QtQt Creator的快速普及,我们花费大量精力写出了这一系列教程。虽然教程的知识可能很浅显,虽然教程的语言可能不规范,但是它却被数十万网友所认可。我们会将这一系列教程一直写下去,它将涉及Qt的方方面面 一、Qt Creator的安装和hello world程序的编写 二、Qt Creator编写多窗口程序 三、Qt Creator登录对话框 四、Qt Creator添加菜单图标 五、Qt Creator布局管理器的使用 六、Qt Creator实现文本编辑 七、Qt Creator实现文本查找 八、Qt Creator实现状态栏显示 九、Qt Creator中鼠标键盘事件的处理实现自定义鼠标指针 十、Qt Creator中实现定时器和产生随机数 十一、Qt 2D绘图(一)绘制简单图形 十二、Qt 2D绘图(二)渐变填充 十三、Qt 2D绘图(三)绘制文字 十四、Qt 2D绘图(四)绘制路径 十五、Qt 2D绘图(五)显示图片 十六、Qt 2D绘图(六)坐标系统 十七、Qt 2D绘图(七)Qt坐标系统深入 十八、Qt 2D绘图(八)涂鸦板 十九、Qt 2D绘图(九)双缓冲绘图简介 二十、Qt 2D绘图(十)图形视图框架简介 二十一、Qt数据库(一)简介 二十二、Qt数据库(二)添加MySQL数据库驱动插件 二十三、Qt数据库(三)利用QSqlQuery类执行SQL语句(一) 二十四、Qt数据库(四)利用QSqlQuery类执行SQL语句(二) 二十五、Qt数据库(五)QSqlQueryModel 二十六、Qt数据库(六)QSqlTableModel 二十七、Qt数据库(七)QSqlRelationalTableModel 二十八、Qt数据库(八)XML(一) 二十九、Qt数据库(九)XML(二) 三十、Qt数据库(十)XML(三) 三十一、Qt 4.7.0及Qt Creator 2.0 beta版安装全程图解 三十二、第一个Qt Quick程序(QML程序) 三十三、体验QML演示程序 三十四、Qt Quick Designer介绍 三十五、QML组件 三十六、QML项目之Image和BorderImage 三十七、Flipable、Flickable和状态与动画 三十八、QML视图 三十九、QtDeclarative模块 四十、使用Nokia Qt SDK开发Symbian和Maemo终端软件 四十一、Qt网络(一)简介 四十二、Qt网络(二)HTTP编程 四十三、Qt网络(三)FTP(一) 四十四、Qt网络(四)FTP(二) 四十五、Qt网络(五)获取本机网络信息 四十六、Qt网络(六)UDP 四十七、Qt网络(七)TCP(一) 四十八、Qt网络(八)TCP(二)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

文火冰糖的硅基工坊

你的鼓励是我前进的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值