簡述
QTimer類提供了重復和單次觸發信號的定時器。
QTimer類為定時器提供了一個高級別的編程接口。很容易使用:首先,創建一個QTimer,連接timeout()信號到適當的槽函數 , 並調用start(),然后在恆定的時間間隔會發射timeout()信號。
注意:當QTimer的父對象被銷毀時,它也會被自動銷毀。
詳細說明
1秒(1000毫秒)更新一次:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
//Widget::Widget(QWidget *parent)
// : QWidget(parent)
//{
// QTimer *timer = new QTimer(this);
// QObject::connect(timer,&QTimer::timeout,this,[=](){
// qDebug() <<"定時器觸發了";
// });
// timer->start();// 缺省就是0毫妙
//}
start()之后,每秒都會調用update()
。 可以通過設置setSingleShot(true)來讓定時器只執行一次。也可以使用靜態函數QTimer::singleShot():
QTimer::singleShot(200, this, SLOT(updateCaption()));
在多線程程序中,可以在一個有事件循環的任何線程中使用QTimer。使用QThread::exec(),從非GUI線程啟動一個事件循環。
Qt使用定時器的線程關聯,以確定哪個線程會發出timeout()信號。正因為如此,你必須在它的線程中啟動和停止定時器,不可能從另一個線程啟動定時器。
作為一個特例,一旦窗口系統事件隊列中的所有事件都已經被處理完,一個定時為0的QTimer就會到時間了。當需要提供流暢的用戶界面時,可以用這來做比較繁重的工作。
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(processOneThing()));
timer->start();
這時,processOneThing()將會被重復調用並且應該很快返回(通常在處理一個數據項之后),這樣Qt可以把事件傳送給窗口部件,並且一旦它完成這個工作就停止這個定時器。這是在圖形用戶界面應用程序中實現繁重的工作的一個典型方法,現在多線程可以在越來越多的平台上使用,我們希望0-毫秒QTimer對象最終被線程替代。 其實這樣是不對的,能有代替多線程的方案盡量不用多線程。
精度
定時器的精度取決於底層操作系統和硬件。絕大多數平台支持精度為1毫秒,盡管定時器的准確性在許多現實世界的情況下和這不相符。
准確性也取決於定時器類型(Qt::TimerType)。對於Qt::PreciseTimer來說,QTimer將試圖保持精確度在1毫秒。精確的定時器也從來不會比預計的還要早超時。
對於Qt::CoarseTimer和Qt::VeryCoarseTimer類型,QTimer可能早於預期,在間隔之內被喚醒:Qt::CoarseTimer為間隔的5%,Qt::VeryCoarseTimer為500毫秒。
枚舉Qt::TimerType:
常量 | 值 | 描述 |
---|---|---|
Qt::PreciseTimer | 0 | 精確的定時器,盡量保持毫秒精度。 |
Qt::CoarseTimer | 1 | 粗略的定時器,盡量保持精度在所需的時間間隔5%范圍內。 |
Qt::VeryCoarseTimer | 2 | 很粗略的定時器,只保留完整的第二精度。 |
在UNIX (包括: Linux、OS X、iOS)中,Qt將為Qt::PreciseTimer保持毫秒精度,對於Qt::CoarseTimer,間隔將調整到5%,使定時器與其他定時器匹配或在差不多在同一時間,目標是讓大多數定時器在同一時間醒來,從而減少CPU喚醒和功耗。
在Windows上,Qt將為Qt::PreciseTimer使用Windows的多媒體定時器工具(如果可用),為Qt::CoarseTimer和Qt::VeryCoarseTimer使用正常的Windows定時器。
所有平台上,Qt::VeryCoarseTimer的間隔被四舍五入到最接近完整的第二位(例如:23500ms的時間間隔將被舍入到24000ms,20300ms舍入至20000)。
替代QTimer
-
另一個使用QTimer的方法:為你的對象調用QObject::startTimer(),在你的類中(必須繼承QObject)重新實現QObject::timerEvent()事件處理器。缺點是timerEvent()不支持像單次觸發定時器或信號那樣的高級特性。
-
另一個選擇是QBasicTimer。它通常比使用QObject::startTimer() 直接。可以查看助手中Timers描述的三種方法。
一些操作系統限制可能會限制定時器的數量,Qt會盡力在限制范圍內工作。
可參考:QBasicTimer、QTimerEvent、QObject::timerEvent()、Timers、Analog Clock Example、Wiggly Example。
成員函數
bool isActive() const
如果定時器正在運行,返回true,否則返回false。
int remainingTime() const
返回定時器的剩余時間(毫秒為單位),直到超時。
如果定時器不活躍,返回值是-1。如果定時器過期,返回值為0。
void setInterval(int msec)
設置超時間隔(毫秒為單位)。
默認值是0,這時,一旦窗口系統事件隊列中的所有事件都已經被處理完,一個時間間隔為0的QTimer就會觸發。
void setSingleShot(bool singleShot)
設置定時器是否為單次觸發。
單次觸發定時器只觸發一次,非單次的話,則每過一個時間間隔都會觸發。
void setTimerType(Qt::TimerType atype)
設置定時器的准確性。默認值是Qt::CoarseTimer。
int timerId() const
如果定時器正在運行,返回定時器的ID,否則返回-1。
void start(int msec)
啟動或重新啟動一個超時時間間隔為毫秒的定時器。
如果定時器正在運行,它將被停止和重新啟動。如果singleShot為true,定時器將只激活一次。
void start()
同上,重載了start()。
void stop()
停止定時器。
信號
void timeout()
定時器超時后,這個信號被發射。
注意:這是一個私有的信號。它可以在信號連接使用,但不能由用戶發出。
示例
下面,我們以QTimer為例,利用開始和停止按鈕來操作一個進度條的更新。
// .h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QProgressBar>
#include <QTimer>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
QProgressBar *m_progressbar;
QTimer *m_timer;
private slots:
void updataProgressBar();
};
#endif // WIDGET_H
//.cpp
#include "widget.h"
#include <QDebug>
#include <QPushButton>
#include <QHBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn_start = new QPushButton(this);
QPushButton *btn_stop = new QPushButton(this);
m_progressbar = new QProgressBar(this);
m_timer = new QTimer(this);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(m_progressbar);
layout->addWidget(btn_start);
layout->addWidget(btn_stop);
setLayout(layout);
btn_start->setText(tr("start"));
btn_stop->setText(tr("stop"));
m_progressbar->setOrientation(Qt::Horizontal);
m_progressbar->setRange(0,100);
m_progressbar->setValue(0);
// 設置時間間隔
m_timer->setInterval(1000);
//singal slots
connect(btn_start,&QPushButton::clicked,m_timer,static_cast<void(QTimer::*)()>(&QTimer::start));
connect(btn_stop,&QPushButton::clicked,m_timer,&QTimer::stop);
connect(m_timer,&QTimer::timeout,this,&Widget::updataProgressBar);
}
Widget::~Widget()
{
}
void Widget::updataProgressBar()
{
// 獲取當前進度值,+1
int nCurrentValue = m_progressbar->value();
++nCurrentValue;
if(nCurrentValue >=100){
m_timer->stop();
}
// 設置新的進度值
m_progressbar->setValue(nCurrentValue);
}
在槽函數updataProgressBar()中,首先通過m_progressbar->value()來獲取當前進度值,然后加1,當進度大於等於100時停止定時器(再繼續執行已經沒任何意義了,因為進度已經達到了100,而且不停止還消耗資源),然后設置進度條的值。
參考處 :https://blog.csdn.net/liang19890820/article/details/51789796