在Qt中使用定時(shí)器有兩種方法,一種是使用QObiect類(lèi)的定時(shí)器;一種是使用QTimer類(lèi)。定時(shí)器的精確性依賴(lài)于操作系統(tǒng)和硬件,大多數(shù)平臺(tái)支持20ms的精確度。
1.QObject類(lèi)的定時(shí)器
QObject是所有Qt對(duì)象的基類(lèi),它提供了一個(gè)基本的定時(shí)器。通過(guò)QObject::startTimer(),可以把一個(gè)一毫秒為單位的時(shí)間間隔作為參數(shù)來(lái)開(kāi)始定時(shí)器,這個(gè)函數(shù)返回一個(gè)唯一的整數(shù)定時(shí)器的標(biāo)識(shí)符。這個(gè)定時(shí)器開(kāi)始就會(huì)在每一個(gè)時(shí)間間隔"觸發(fā)",直到明確的使用這個(gè)定時(shí)器的標(biāo)識(shí)符來(lái)調(diào)用QObject::killTimer()結(jié)束。
當(dāng)定時(shí)器觸發(fā)時(shí),應(yīng)用程序會(huì)發(fā)送一個(gè)QTimerEvent。在事件循環(huán)中,處理器按照事件隊(duì)列的順序來(lái)處理定時(shí)器事件。當(dāng)處理器正忙于其它事件處理時(shí),定時(shí)器就不能立即處理。
QObject類(lèi)還提供定時(shí)期的功能。與定時(shí)器相關(guān)的成員函數(shù)有:startTimer()、timeEvent()、killTimer()。QObject基類(lèi)中的startTimer()和timerEvent()原型及說(shuō)明如下:
intQObject::startTimer(int interval);
開(kāi)始一個(gè)定時(shí)器并返回定時(shí)器ID,如果不能開(kāi)始一個(gè)定時(shí)器,將返回0。定時(shí)器開(kāi)始后,每隔interval毫秒間隔將觸發(fā)一次超時(shí)事件,直到killTimer()被調(diào)用來(lái)刪除定時(shí)器。如果interval為0,那么定時(shí)器事件每次發(fā)生時(shí)沒(méi)有窗口系統(tǒng)事件處理。
virtual voidQObject::timerEvent(QTimerEvent *event);
虛函數(shù)timerEvent()被重載來(lái)實(shí)現(xiàn)用戶(hù)的超時(shí)事件處理函數(shù)。如果有多個(gè)定時(shí)器在運(yùn)行,QTimerEvent::timerId()被用來(lái)查找指定定時(shí)器,對(duì)其進(jìn)行操作。
當(dāng)定時(shí)器事件發(fā)生時(shí),虛函數(shù)timerEvent()隨著QTimerEvent事件參數(shù)類(lèi)一起被調(diào)用,重載這個(gè)函數(shù)可以獲得定時(shí)器事件。
定時(shí)器的用法如下:
//頭文件
class QNewObject : publicQObject
{
Q_OBJECT
public:
QNewObject( QObject * parent = 0 );
virtual ~QNewObject();
protected:
void timerEvent( QTimerEvent *event );
int m_nTimerId;
};
//源文件
QNewObject::QNewObject(QObject * parent )
:QNewObject( parent )
{
m_nTimerId = startTimer(1000);
}
QNewObject::~QNewObject()
{
if ( m_nTimerId != 0 )
killTimer(m_nTimerId);
}
voidQNewObject::timerEvent( QTimerEvent *event )
{
qDebug( "timer event, id %d",event->timerId() );
}
2.定時(shí)器類(lèi)QTimer
定時(shí)器類(lèi)QTimer提供當(dāng)定時(shí)器觸發(fā)的時(shí)候發(fā)射一個(gè)信號(hào)的定時(shí)器,他提供只觸發(fā)一次的超時(shí)事件,通常的使用方法如下:
//創(chuàng)建定時(shí)器
QTimer *testTimer = newQTimer(this);
//將定時(shí)器超時(shí)信號(hào)與槽(功能函數(shù))聯(lián)系起來(lái)
connect( testTimer,SIGNAL(timeout()), this, SLOT(testFunction()) );
//開(kāi)始運(yùn)行定時(shí)器,定時(shí)時(shí)間間隔為1000ms
testTimer->start(1000);
...
//停止運(yùn)行定時(shí)器
if (testTimer->isActive() )
testTimer->stop();
QTimer還提供了一個(gè)簡(jiǎn)單的只有一次定時(shí)的函數(shù)singleShot()。 一個(gè)定時(shí)器在100ms后觸發(fā)處理函數(shù)animateTimeout()并且只觸發(fā)一次。代碼如下:
QTimer::singleShot( 100,this, SLOT(animateTimeout()) );
QTimer類(lèi)提供了定時(shí)器信號(hào)和單觸發(fā)定時(shí)器。
它在內(nèi)部使用定時(shí)器事件來(lái)提供更通用的定時(shí)器。QTimer很容易使用:創(chuàng)建一個(gè)QTimer,使用start()來(lái)開(kāi)始并且把它的timeout()連接到適當(dāng)?shù)牟邸.?dāng)這段時(shí)間過(guò)去了,它將會(huì)發(fā)射timeout()信號(hào)。
注意當(dāng)QTimer的父對(duì)象被銷(xiāo)毀時(shí),它也會(huì)被自動(dòng)銷(xiāo)毀。
實(shí)例:
QTimer *timer = new QTimer( myObject );
connect( timer, SIGNAL(timeout()),myObject, SLOT(timerDone()) );
timer->start( 2000, TRUE ); // 2秒單觸發(fā)定時(shí)器
你也可以使用靜態(tài)的singleShot()函數(shù)來(lái)創(chuàng)建單觸發(fā)定時(shí)器。
作為一個(gè)特殊情況,一旦窗口系統(tǒng)事件隊(duì)列中的所有事件都已經(jīng)被處理完,一個(gè)定時(shí)為0的QTimer就會(huì)到時(shí)間了。
這也可以用來(lái)當(dāng)提供迅速的用戶(hù)界面時(shí)來(lái)做比較繁重的工作。
QTimer *t = new QTimer( myObject );
connect( t, SIGNAL(timeout()), SLOT(processOneThing()));
t->start( 0, FALSE );
myObject->processOneThing()將會(huì)被重復(fù)調(diào)用并且應(yīng)該很快返回(通常在處理一個(gè)數(shù)據(jù)項(xiàng)之后),這樣Qt可以把事件傳送給窗口部件并且一旦它完成這個(gè)工作就停止這個(gè)定時(shí)器。這是在圖形用戶(hù)界面應(yīng)用程序中實(shí)現(xiàn)繁重的工作的一個(gè)典型方法,現(xiàn)在多線(xiàn)程可以在越來(lái)越多的平臺(tái)上使用,并且我們希望無(wú)效事件最終被線(xiàn)程替代。
注意QTimer的精確度依賴(lài)于底下的操作系統(tǒng)和硬件。絕大多數(shù)平臺(tái)支持20毫秒的精確度,一些平臺(tái)可以提供更高的。如果Qt不能傳送定時(shí)器觸發(fā)所要求的數(shù)量,它將會(huì)默默地拋棄一些。
另一個(gè)使用QTimer的方法是為你的對(duì)象調(diào)用QObject::startTimer()和在你的類(lèi)中(當(dāng)然必須繼承QObject)重新實(shí)現(xiàn)QObject::timerEvent()事件處理器。缺點(diǎn)是timerEvent()不支持像單觸發(fā)定時(shí)器或信號(hào)那樣的高級(jí)水平。
一些操作系統(tǒng)限制可能用到的定時(shí)器的數(shù)量,Qt會(huì)盡力在限制范圍內(nèi)工作。