QTimer


簡述

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM