QTimer 定時器

QTimer類爲我們提供了一個即可重複觸發又可單次觸發的定時器。它是一個高層次的應用程序接口。要使用它,只需創建一個QTimer類對象,將它的timeout()信號連接到適當的函數上,然後調用其start()函數開啓定時器即可,此後,QTimer對象就會週期性的發出timeout()信號。

例如,一個1s執行一次的定時器,可以如下設置:

      QTimer *timer = new QTimer(this);
      connect(timer, SIGNAL(timeout()), this, SLOT(update()));
      timer->start(1000);
這樣,update()就會每隔1秒被調用一次。

當然,我們也可以讓一個QTimer對象在啓動後只觸發一次,只需調用該類的setSingleShot(true)即可。其實,更簡單的做法是使用該類的靜態方法QTimer::singleShot(),以某個時間間隔來啓動一個單次觸發的定時器。例如:

QTimer::singleShot(2000, this, SLOT(updateCaption()));
上面這句代碼執行結束,2s後會調用一次updateCaption(),並且只調用一次。

要注意的是在多線程程序中,我們可以在任何開啓了事件循環的線程中啓動定時器。而要在一個非GUI線程中開啓事件循環,則需要調用QThread::exec()。而Qt會使用定時器的線程依附性來決定由哪個線程發出timeout()信號。鑑於此,必須在定時器對象所在的線程中開啓和結束定時器,不能跨線程操作。

比較特殊的一點是,在構建QTimer 對象時,可以傳入0作爲時間間隔。這樣的定時器會在窗口系統的事件隊列中的事件都被處理完之後觸發。這可以用來在GUI程序中處理一些後臺任務,比如垃圾收集。

下面我們使用QTimer類,來週期性的改變窗口的背景圖片。

新建一個GUI工程Timer,完成後,在工程上點擊右鍵,添加新文件,選中Qt Resource File,將我們需要的圖片作爲資源加入到工程中。如下圖:



點擊 Choose,在爲資源文件起一個名字即可。如下圖:



點擊 下一步,在點擊完成即可。

完成後,會在工程目錄中生成一個資源目錄,如下圖:


然後,在res.qrc上,右鍵->open in editor,打開資源編輯器。如下圖:


點擊 添加->添加前綴,添加一個簡單的前綴即可,一般在 前綴 那一欄填入"/"即可。

在點擊 添加->添加文件 ,將準備好的圖片添加進來即可。添加完成後,如下圖:


這樣,我們就可以在代碼中使用這些圖片了。至於Qt的資源系統,大家有時間的話可以自行參考Qt幫助文檔學習,此處就不展開講了。


先來看頭文件widget.h的代碼:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void paintEvent(QPaintEvent*);

private slots:
    void timeout();

private:
    Ui::Widget *ui;
    QTimer* timer;
    QImage images[12];
    int index;
};

#endif // WIDGET_H
在頭文件中,我們先重寫了paintEvent()事件,該事件就是用來重繪窗口的,我們以會就是在這個函數中向界面上繪製我們的圖片。然後我們還定義了一個timeout()槽函數,該函數用來響應定時器QTimer的timeout()信號(注意,不要和上面的timeout()搞混,一個是槽,一個是信號,此處只是名字而已,大家在可以將上面的槽函數timeout()改爲其他的名字)。最後,我們定義了一個定時器對象,一個QImage圖片數組,用來存儲我們的12張星座圖片,還定義了一個index下標,用來在每次界面重繪的事件中標識不同的圖片。

下面來看一個窗口的構造函數:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    images[0] = QImage(":/images/1.jpg");
    images[1] = QImage(":/images/2.jpg");
    images[2] = QImage(":/images/3.jpg");
    images[3] = QImage(":/images/4.jpg");
    images[4] = QImage(":/images/5.jpg");
    images[5] = QImage(":/images/6.jpg");
    images[6] = QImage(":/images/7.jpg");
    images[7] = QImage(":/images/8.jpg");
    images[8] = QImage(":/images/9.jpg");
    images[9] = QImage(":/images/10.jpg");
    images[10] = QImage(":/images/11.jpg");
    images[11] = QImage(":/images/12.jpg");

    index = 0;

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
    timer->start(1000);
}
在構造函數中,我們先使用我們添加的資源圖片初始化了我們的圖片數組,注意Qt中使用資源加載圖片的方式,已":"開始,後面是圖片在資源文件中的具體路徑。然後,將index初始化爲0,即重第一張圖片開始顯示。最後,實例化定時器對象,連接其timeout()信號到我們定義的timeout()槽函數上,再以1s爲間隔啓動定時器。

timeout()槽函數實現如下:

void Widget::timeout()
{
    update();
}
在定時器到期函數中,我們只是簡單的調用了QWidget類的update()函數,該函數會觸發窗口的重繪,即會觸發paintEvent()函數的調用。

paintEvent()實現如下:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawImage(rect(), images[index++ % 12]);
}
在paintEvent()函數中,我們每次將下標index % 12 表示的圖片繪製到窗口上,然後將index自增。從而實現12張圖片的輪播。

啓動程序,運行結果如下,12張星座圖片以1s爲間隔,不斷在窗口中輪播:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章