Qt兩種定時器使用實現(xiàn)方式
QT 中使用定時器,有兩種方式:
- 定時器類:
QTimer
- 定時器事件:
QEvent::Timer
,對應的子類是QTimerEvent
簡單講一下兩種用法:
QTimer:
QTimer 需要創(chuàng)建QTimer對象
- 然后需要給定時器綁定 定時器超時的槽函數,也就是時間到了,該做什么
- 一般用按鈕控制定時器,所以跟按鈕關聯(lián)的槽函數一般里面有start,stop就是控制定時器的
- 這樣通過按鈕點擊之后,調用里面Qtimer的start,因為外面綁定了定時器超時槽函數,所以
- 定時器到時間了就會調用超時槽函數,完成業(yè)務邏輯
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 * 用兩種都去實現(xiàn)一下 * 1.QTimerEvent * 需要重寫void QObject::timerEvent(QTimerEvent *event) * 當定時時間到的時候會自動調用timerEvent * 用timerid可以獲取哪個定時器的id * startTimer()可以設置定時器時間間隔 ms * killTimer停止定時器 * * 2. *QTimer 需要創(chuàng)建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是最優(yōu)的定時器方案,有現(xiàn)成的封裝的很完善的功能,就用 QTimer就行。
使用QTimer的另一種選擇是為你的對象調用QObject::startTimer(),并在你的類(必須繼承QObject)中重新實現(xiàn)QObject::timerEvent()事件處理程序。缺點是timerEvent()不支持諸如單觸發(fā)定時器或信號之類的高級特性。
另一個替代方法是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(); }
一些操作系統(tǒng)會限制可能使用的定時器的數目。Qt試圖繞過這些限制。
總結
到此這篇關于Qt兩種定時器使用的文章就介紹到這了,更多相關Qt定時器使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!