QTimer使用问题

  • 1. 概述
  • 2. 使用场景
    • 2.1 注意
    • 2.2 主线程中使用
    • 2.3 子线程中使用
      • 2.3.1 moveToThread
      • 2.3.2 QThread
        • 2.3.2.1 定时器不能在另一个线程启动问题演示

1. 概述

QT中使用定时器QTimer时,一不小心可能就会造成定时器失效的情况,这个问题的本质是QTimer实例运行在了一个没有启用事件循环的线程中,从而造成其失效

2. 使用场景

  • 主线程中使用
  • 子线程中使用

2.1 注意

定时器的创建与使用要在同一个线程中,这个问题的演示会在2.2.2 QThread小节中进行

2.2 主线程中使用

  1. 首先创建一个QTimerInMainThread类,内容如下:

    #ifndef QTIMERRUNINTHREAD_H
    #define QTIMERRUNINTHREAD_H#include <QObject>
    #include <QTimer>class QTimerInMainThread : public QObject
    {Q_OBJECT
    public:QTimerInMainThread();~QTimerInMainThread();QTimer m_timer;int m_count;
    public slots:void timeoutHandle();};#endif // QTIMERRUNINTHREAD_H
    
  2. 实现QTimerInMainThread
    #include "QTimerRunInThread.h"
    #include <QThread>
    #include <QDebug>QTimerInMainThread::QTimerInMainThread(): m_count(0)
    {QObject::connect(&m_timer,&QTimer::timeout,this,&QTimerInMainThread::timeoutHandle);m_timer.start(100);
    }QTimerInMainThread::~QTimerInMainThread()
    {m_timer.stop();
    }void QTimerInMainThread::timeoutHandle()
    {qDebug() << "current thread id: " <<  QThread::currentThreadId() << "m_count: " << m_count++;
    }
  3. main.cpp
#include <QCoreApplication>
#include "QTimerObjectInQThread.h"
#include <QDebug>
#include <QThread>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "main thread id: " <<  QThread::currentThreadId() ;/** 第一种方式:定时器运行在主线程中*  直接主线程中启动一个定时器*/static QTimerInMainThread mainThreadTimer;return a.exec();
}

2.3 子线程中使用

QT中线程的使用通常分为两种,接下来就以这两种进行举例。

2.3.1 moveToThread

  1. 创建QTimerMoveToChildrenThread

    #ifndef QTIMERMOVETOCHILDRENTHREAD_H
    #define QTIMERMOVETOCHILDRENTHREAD_H#include <QObject>
    #include <QTimer>
    #include <QThread>class QTimerMoveToChildrenThread: public QObject
    {Q_OBJECT
    public:QTimerMoveToChildrenThread();~QTimerMoveToChildrenThread();void start();void stop();QTimer m_timer;QThread m_timerThread;int m_count;signals:void startSignal(int msec);void stopSignal();public slots:void timeoutHandle();
    };#endif // QTIMERMOVETOCHILDRENTHREAD_H
  2. 实现QTimerMoveToChildrenThread
    #include "QTimerMoveToChildrenThread.h"
    #include <QDebug>QTimerMoveToChildrenThread::QTimerMoveToChildrenThread(): m_count(0)
    {// 更改定时器运行的线程m_timer.moveToThread(&m_timerThread);// 定时器触发事件connect(&m_timer,&QTimer::timeout,this,&QTimerMoveToChildrenThread::timeoutHandle);// 连接定时器启动槽函数QObject::connect(this,static_cast<void (QTimerMoveToChildrenThread::*)(int)>(&QTimerMoveToChildrenThread::startSignal),&m_timer,static_cast<void (QTimer::*)(int)>(&QTimer::start));// 连接定时器关闭槽函数QObject::connect(this,&QTimerMoveToChildrenThread::stopSignal,&m_timer,&QTimer::stop);m_timerThread.start();
    }QTimerMoveToChildrenThread::~QTimerMoveToChildrenThread()
    {stop();m_timerThread.quit();
    }void QTimerMoveToChildrenThread::start()
    {//向子线程内的定时器发送开启定时器信号emit startSignal(100);
    }void QTimerMoveToChildrenThread::stop()
    {//向子线程内的定时器发送停止定时器信号emit stopSignal();
    }void QTimerMoveToChildrenThread::timeoutHandle()
    {// 这个在主线程中执行qDebug() << "current thread id: " <<  QThread::currentThreadId() << "m_count: " << m_count++;
    }
    
  3. main.cpp
    #include <QCoreApplication>
    #include "QTimerMoveToChildrenThread.h"
    #include <QDebug>
    #include <QThread>int main(int argc, char *argv[])
    {QCoreApplication a(argc, argv);qDebug() << "main thread id: " <<  QThread::currentThreadId() ;/** 第二种方式:定时器运行在子线程中*  将定时器移动到子线程中,外部发送启动信号启动子线程中的定时器*/static QTimerMoveToChildrenThread moveToChildrenThreadTimer;moveToChildrenThreadTimer.start();return a.exec();
    }
    

2.3.2 QThread

  1. 创建QTimerObjectInQThread
#ifndef QTIMEROBJECTINQTHREAD_H
#define QTIMEROBJECTINQTHREAD_H#include <QObject>
#include <QThread>
#include <QTimer>class QTimerObjectInQThread : public QThread
{Q_OBJECT
public:QTimerObjectInQThread();~QTimerObjectInQThread();QTimer* m_ptimer;int m_count;public slots:void timeoutHandle();protected:virtual void run() override;
};#endif // QTIMEROBJECTINQTHREAD_H
  1. 实现QTimerObjectInQThread
#include "QTimerObjectInQThread.h"
#include <QDebug>QTimerObjectInQThread::QTimerObjectInQThread(): m_count(0)
{}QTimerObjectInQThread::~QTimerObjectInQThread()
{if(m_ptimer){m_ptimer->stop();delete m_ptimer;}
}void QTimerObjectInQThread::timeoutHandle()
{qDebug() << "current thread id: " <<  QThread::currentThreadId() << "m_count: " << m_count++;
}void QTimerObjectInQThread::run()
{m_ptimer = new QTimer;connect(m_ptimer,&QTimer::timeout,this,&QTimerObjectInQThread::timeoutHandle);m_ptimer->start(100);// 启动事件循环,否则定时器无法生效exec();
}
  1. main.cpp
#include <QCoreApplication>
#include "QTimerRunInThread.h"
#include "QTimerMoveToChildrenThread.h"
#include "QTimerObjectInQThread.h"
#include <QDebug>
#include <QThread>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "main thread id: " <<  QThread::currentThreadId() ;/** 第二种方式:定时器运行在子线程中*  在线程的run()中启动定时器*/QTimerObjectInQThread timerObjectInThread;timerObjectInThread.start();return a.exec();
}

2.3.2.1 定时器不能在另一个线程启动问题演示

  1. QTimer* m_ptimer;修改为QTimer m_ptimer;
  2. QTimerObjectInQThread类的实现修改如下
    #include "QTimerObjectInQThread.h"
    #include <QDebug>QTimerObjectInQThread::QTimerObjectInQThread(): m_count(0)
    {}QTimerObjectInQThread::~QTimerObjectInQThread()
    {//    if(m_ptimer)
    //    {//        m_ptimer->stop();
    //        delete m_ptimer;
    //    }
    }void QTimerObjectInQThread::timeoutHandle()
    {qDebug() << "current thread id: " <<  QThread::currentThreadId() << "m_count: " << m_count++;
    }void QTimerObjectInQThread::run()
    {//m_ptimer = new QTimer;connect(&m_ptimer,&QTimer::timeout,this,&QTimerObjectInQThread::timeoutHandle);m_ptimer.start(100);// 启动事件循环,否则定时器无法生效exec();
    }
  3. 运行项目会输出以下内容
    QObject::startTimer: Timers cannot be started from another thread

QTimer使用问题相关推荐

  1. QT 中QTimer 和 startTimer()的区别

    最需要注意一点 请注意,QTimer的准确性取决于底层操作系统和硬件.timerType参数允许您自定义计时器的准确性.有关不同计时器类型的信息,请参见Qt::TimerType.大多数平台支持20毫 ...

  2. Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

    目录 1.QTimer计时器类 2.QThread多线程类 3.事件处理类 一般情况下,应用程序都是单线程运行的,但是对于GUI程序来说,单线程有时候满足不了需求.例如,如果需要执行一个特别耗时的操作 ...

  3. pyqt5 使用 QTimer, QThread, pyqtSignal 实现自动执行,多线程,自定义信号触发。

    渣渣用法,请等待我心情好的时候更新. 1.第一个例子 1.1 先看mainwindow.py from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Ma ...

  4. Qt中的QTimer

    文章目录 1 Qt中的QTimer 1 Qt中的QTimer 计时器的概念: 计时器是工程开发中非常重要的角色. 计时器用于每隔一定的时间触发一个消息. 计时器消息最终会被转换为函数调用. 宏观上: ...

  5. Qt学习(七):定时器QTimer

    知识点 Qt中定时器QTimer的使用 完整项目github地址: https://github.com/taw19960426/Qt_study/tree/main/QTimer 结果演示 widg ...

  6. Qt: QTimer和QThread

    让QTimer 跑在其他线程. 一般写法如下. 1. 在main thread中为worker thread指定定时器. QThread* thread = new QThread(this);thr ...

  7. QT的QTimer类的使用

    详细说明 QTimer类提供重复和单次计时器. QTimer类为计时器提供了高级编程接口.要使用它,请创建一个QTimer,将其timeout()信号连接到适当的插槽,然后调用start().从那时起 ...

  8. Qt定时器QBasicTimer、startTimer、QTimer使用总结

    QBasicTimer 这个定时器类是一个 轻量级的.较底层的.被Qt内部使用的定时器类.如果在你的应用程序中使用定时器类,推荐使用QTimer类,而不是这个类.该类和QTimer类类似,也提供sta ...

  9. linux+qt+定时精度,Qt QTimer测试定时精度

    调试信息输出窗口可以查看超时误差 dialog.h文件 #ifndef DIALOG_H #define DIALOG_H #include #include namespace Ui { class ...

  10. [转]QT QDateTime类、QTimer类

    QDateTime类,头文件#include <QDateTime> 可以使用QDateTime类来获得系统时间.通过QDateTime::currentDateTime()来获取本地系统 ...

最新文章

  1. mysql 连接 查询 连表查询
  2. [Objective-c基础教程] chapter one Before You Start chapter two Extensions to C
  3. 知乎上 40 个有趣回复,很精辟!
  4. 《Effective C#》读书笔记——条目19:保证0为值类型的有效状态.NET资源管理
  5. unc0ver 发布新版本支持 iOS 13.3 越狱
  6. python 输出当前行号
  7. html按钮返回上一步操作,用js实现返回上一步操作
  8. UVa 621 - Secret Research
  9. Java实现Oracle数据库导入
  10. Java实现打印进度条
  11. C#查看打印机状态(缺纸)
  12. css 设置手机浏览器背景图片填充整个页面的小问题级解决方法
  13. 【​观察】做好数据到介质的连接者 新数据时代浪潮存储的行与思
  14. 电脑连接电视的方法---HDMI篇
  15. 电脑无法连接WiFi(显示地球图标)
  16. webstorm插件使用
  17. 汽车网络安全:TEE是否能够取代HSM?
  18. python验证身份证最后一位数字代表什么_身份证号最后一位是“X”,代表什么意思?...
  19. PHP新浪乐居面试题,一个朋友去新浪乐居应聘时的面试题_PHP教程
  20. [Unity]实现按住WASD角色移动

热门文章

  1. 自适应旁瓣对消基本原理(SLC)
  2. 【数据结构与算法】之深入解析“斐波那契数”的求解思路与算法示例
  3. 头部大模型公司进京赶考,向量数据库成为应考神器
  4. Delphi中票据条码的打印中(像素)和厘米的换算关系
  5. 仓库管理系统GreaterWMS的安装
  6. win7怎么设置计算机的性能,win7怎么提升电脑性能
  7. 虚拟机ubuntu下使用gstreamer推流学习笔记(四)简易的.mkv格式视频播放器
  8. 开元媒体观察之:传统媒体的生死劫与重大机遇——百亿级网络版权平台或将诞生
  9. 学了四年的电路,却看不懂电路图?
  10. 指纹识别中的傅里叶变换