Qt两种定时器使用实现方式

 更新时间:2024年01月30日 15:24:17   作者:锅巴大王  
这篇文章主要给大家介绍了关于Qt两种定时器使用实现方式的相关资料,Qt中的定时器类是QTimer,QTimer不是一个可见的界面组件,文中通过代码介绍的非常详细,需要的朋友可以参考下

QT 中使用定时器,有两种方式:

  • 定时器类:QTimer
  • 定时器事件:QEvent::Timer,对应的子类是 QTimerEvent

简单讲一下两种用法:

QTimer:

QTimer 需要创建QTimer对象

  •   然后需要给定时器绑定 定时器超时的槽函数,也就是时间到了,该做什么
  •  一般用按钮控制定时器,所以跟按钮关联的槽函数一般里面有start,stop就是控制定时器的
  •  这样通过按钮点击之后,调用里面Qtimer的start,因为外面绑定了定时器超时槽函数,所以
  •  定时器到时间了就会调用超时槽函数,完成业务逻辑

QTimerEvent:

  •  需要重写void QObject::timerEvent(QTimerEvent *event)
  •  当定时时间到的时候会自动调用timerEvent
  •  用timerId可以获取哪个定时器的id
  •  startTimer()可以设置定时器时间间隔 ms
  •  killTimer停止定时器

对于 QTimerEvent不用重写定时器超时函数并且再手动绑定,QTimerEvent他会自动调用timerEvent,该函数将自动在使用startTimer函数启动的定时器到期时被调用,所以只需要重写这个就行

下面举一个案例:看看实际项目中怎么用

这有一个定时器任务的页面,无ui的,手撕代码去写

.h

#ifndef TIMEREVENT_H
#define TIMEREVENT_H

#include <QWidget>
#include <QTimer>
#include <QTimerEvent>
#include <QLabel>

class TimerEvent : public QWidget
{
    Q_OBJECT
public:
    explicit TimerEvent(QWidget *parent = nullptr);
private slots:
    void startclick();
    void pauseclick();
    void restartclick();

    //用QTimer,定时器超时的槽函数
    void timerout1();
    void timerout2();
private:
    QLabel* lab1;
    QLabel* lab2;
    int id1;
    int id2;
    //QTimer
    QTimer *tm1;
    QTimer *tm2;
private:
    //QTimerEvent
    void timerEvent(QTimerEvent *event);
signals:

};

#endif // TIMEREVENT_H

.cpp

#include "timerevent.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QDebug>

//  定时器事件
/*
 * 做定时器有两种方式,一种QTimer类,一种是QEvent的Timer事件 ,用到的子类是QTimerEvent
 * 用两种都去实现一下
 * 1.QTimerEvent
 * 需要重写void QObject::timerEvent(QTimerEvent *event)
 * 当定时时间到的时候会自动调用timerEvent
 * 用timerid可以获取哪个定时器的id
 * startTimer()可以设置定时器时间间隔 ms
 * killTimer停止定时器
 *
 * 2.
 *QTimer 需要创建QTimer对象
 * 然后需要给定时器绑定 定时器超时的槽函数
 * 一般在按钮里面有start,stop就是控制定时器的
 * 这样通过按钮点击之后,调用里面Qtimer的start,因为外面绑定了定时器超时槽函数,所以
 * 定时器到时间了就会调用超时槽函数
 * 对于 QTimerEvent不用重写超时函数并且去手动绑定,他会自动调用timerEvent,只需要重写这个就行
 * */
TimerEvent::TimerEvent(QWidget *parent) : QWidget(parent)
{
    //垂直布局
    QVBoxLayout *vblayout = new QVBoxLayout(this);
    vblayout->setSpacing(0);
    vblayout->setContentsMargins(0,0,0,0);

    //
    QLabel *ql = new QLabel(this);
    ql->setText("定时器事件");
    ql->setFixedHeight(50);
    ql->setAlignment(Qt::AlignCenter);
    ql->setFrameShape(QFrame::Box);
    ql->setStyleSheet("color:green;font:25px;background-color:rgb(0,233,233);border-radius:10px;"
                      );
    vblayout->addWidget(ql);

    //第一个标签
    lab1 = new QLabel(this);
    lab1->setFixedSize(95,95);
    lab1->setFrameShape(QFrame::Box);
    lab1->setStyleSheet("background-color:yellow");
    vblayout->addWidget(lab1);
    //第二个标签
    lab2 = new QLabel(this);
    lab2->setFixedSize(95,95);
    lab2->setFrameShape(QFrame::Box);
    lab2->setStyleSheet("background-color:purple");
    vblayout->addWidget(lab2);
    //三个按钮
    QPushButton* start= new QPushButton(this);
    start->setText("开始");
    QPushButton* pause= new QPushButton(this);
    pause->setText("暂停");
    QPushButton* restart= new QPushButton(this);
    restart->setText("复位");
    this->setStyleSheet(R"(
                        QPushButton{
                        font-size:20px;
                        })");
    //水平布局
    QHBoxLayout *hb = new QHBoxLayout(this);
    hb->setSpacing(0);
    hb->setContentsMargins(0,0,0,0);

    hb->addWidget(start);
    hb->addWidget(pause);
    hb->addWidget(restart);
    vblayout->addLayout(hb);

    //按键的信号槽
    connect(start,&QPushButton::clicked,this,&TimerEvent::startclick);
    connect(pause,&QPushButton::clicked,this,&TimerEvent::pauseclick);
    connect(restart,&QPushButton::clicked,this,&TimerEvent::restartclick);

    //Qtimer绑定的信号槽
    tm1 = new QTimer(this);
    tm2 = new QTimer(this);
    connect(tm1,&QTimer::timeout,this,&TimerEvent::timerout1);
    connect(tm2,&QTimer::timeout,this,&TimerEvent::timerout2);
}

void TimerEvent::startclick()
{
#ifdef USR_TIMER_EVENT
    qDebug()<<"use timerevent";
    id1=startTimer(10);
    id2=startTimer(20);
#else
    qDebug()<<"use Qtimer";
    tm1->start(10);
    tm2->start(20);
#endif
}

void TimerEvent::pauseclick()
{
#ifdef USR_TIMER_EVENT
    qDebug()<<"use timerevent";
    killTimer(id1);
    killTimer(id2);
#else
    qDebug()<<"use Qtimer";
    tm1->stop();
    tm2->stop();
#endif
}

void TimerEvent::restartclick()
{
    lab1->move(0,lab1->y());
    lab2->move(0,lab2->y());
}
//Qtimer
void TimerEvent::timerout1()
{
    lab1->move(lab1->x()+5,lab1->y());
    if(lab1->x()>=this->width()){
        lab1->move(0,lab1->y());
    }

}

void TimerEvent::timerout2()
{
    lab2->move(lab2->x()+5,lab2->y());
    if(lab2->x()>=this->width()){
        lab2->move(0,lab2->y());
    }
}
//timerevent
void TimerEvent::timerEvent(QTimerEvent *event)
{
    //当定时器时间到了,看是哪个定时器
    if(event->timerId()==id1){
        lab1->move(lab1->x()+5,lab1->y());
        if(lab1->x()>=this->width()){
            lab1->move(0,lab1->y());
        }
    }
    if(event->timerId()==id2){
        lab2->move(lab2->x()+5,lab2->y());
        if(lab2->x()>=this->width()){
            lab2->move(0,lab2->y());
        }
    }
}

附:QTimer的替代方案

第 3点 总的来说,QTimer是最优的定时器方案,有现成的封装的很完善的功能,就用 QTimer就行。

使用QTimer的另一种选择是为你的对象调用QObject::startTimer(),并在你的类(必须继承QObject)中重新实现QObject::timerEvent()事件处理程序。缺点是timerEvent()不支持诸如单触发定时器或信号之类的高级特性。

另一个替代方法是QBasicTimer。这通常比直接使用QObject::startTimer()要简单得多。

  • 替代方法一:
class MyObject : public QObject
  {
      Q_OBJECT

  public:
      MyObject(QObject *parent = nullptr);

  protected:
      void timerEvent(QTimerEvent *event) override;
  };

  MyObject::MyObject(QObject *parent)
      : QObject(parent)
  {
      startTimer(50);     // 50-millisecond timer
      startTimer(1000);   // 1-second timer
      startTimer(60000);  // 1-minute timer

      using namespace std::chrono;
      startTimer(milliseconds(50));
      startTimer(seconds(1));
      startTimer(minutes(1));

      // since C++14 we can use std::chrono::duration literals, e.g.:
      startTimer(100ms);
      startTimer(5s);
      startTimer(2min);
      startTimer(1h);
  }

  void MyObject::timerEvent(QTimerEvent *event)
  {
      qDebug() << "Timer ID:" << event->timerId();
  }

一些操作系统会限制可能使用的定时器的数目。Qt试图绕过这些限制。

总结 

到此这篇关于Qt两种定时器使用的文章就介绍到这了,更多相关Qt定时器使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现的求解多元一次方程示例

    C++实现的求解多元一次方程示例

    这篇文章主要介绍了C++实现的求解多元一次方程,涉及C++矩阵运算相关操作技巧,需要的朋友可以参考下
    2018-01-01
  • C++ 约瑟夫环问题案例详解

    C++ 约瑟夫环问题案例详解

    这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++深浅拷贝和写时拷贝图文详解

    C++深浅拷贝和写时拷贝图文详解

    这篇文章主要给大家介绍了关于C++深浅拷贝和写时拷贝的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • C/C++实现目录监视器的方法详解

    C/C++实现目录监视器的方法详解

    这篇文章主要介绍了C/C++ 实现目录监视器的方法,然后网上查到的基本就有三种方法,使用FindFirstChangeNotification等系列函数,使用ReadDirectoryChangesW函数和使用change journals,本文使用了第二种方式来实现一个目录监视,需要的朋友可以参考下
    2024-04-04
  • C++中线程同步与互斥的四种方式介绍及对比详解

    C++中线程同步与互斥的四种方式介绍及对比详解

    在C++中,当两个或更多的线程需要访问共享数据时,就会出现线程安全问题,这是因为,如果没有适当的同步机制,一个线程可能在另一个线程还没有完成对数据的修改就开始访问数据,这将导致数据的不一致性和程序的不可预测性,本文介绍了C++中线程同步与互斥的四种方式介绍及对比
    2025-01-01
  • C++在成员函数中使用STL的find_if函数实例

    C++在成员函数中使用STL的find_if函数实例

    这篇文章主要介绍了C++在成员函数中使用STL的find_if函数实例,包括了STL中find_if函数的具体用法及相关的完整实例,非常具有参考借鉴价值,需要的朋友可以参考下
    2014-10-10
  • C++实现简单学生管理系统

    C++实现简单学生管理系统

    这篇文章主要为大家详细介绍了C++实现简单学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++命名空间使用详细介绍

    C++命名空间使用详细介绍

    考虑一种情况,当我们有两个同名的人,Zara,在同一个班里。当我们需要对它们进行区分我们必须使用一些额外的信息和它们的名字,比如它们生活在不同的区域或者兴趣爱好什么的,在C++程序中也会遇到同样的情况,所以命名空间就此产生
    2022-09-09
  • 数据结构 红黑树的详解

    数据结构 红黑树的详解

    这篇文章主要介绍了数据结构 红黑树的详解的相关资料,数据结构中的二叉树查找,红黑树的讲解,需要的朋友可以参考下
    2017-07-07
  • C++细讲深浅拷贝与初始化列表如何操作

    C++细讲深浅拷贝与初始化列表如何操作

    C++对象特性里的拷贝构造函数有更深入的含义,而且面试曾经问过关于拷贝的析构问题,那么今天就好好解析一下深浅拷贝的问题;还有初始化列表的形式,这个在给对象属性初始化的时候非常方便,建议大家熟练掌握,话不多说,开始正文
    2022-05-05

最新评论