注意事項:
1、QTimer's accuracy depends on the underlying operating system and hardware.Most platforms support an accuracy of 20 milliseconds; some provide more.
2、If Qt is unable to deliver the requested number of timer events, it will silently discard some.
問題:當開啟一個定時器,設置時間間隔為50ms,它對應的QTimerEvnet處理函數要執行一段耗時的操作,如何讓界面快速響應用戶的鼠標事件呢
代碼:
#include "QtGuiApplication2.h" #include <QDebug> #include <QTimerEvent> #include <QDateTime> #include <QTime> #include <QThread> QtGuiApplication2::QtGuiApplication2(QWidget *parent) : QDialog(parent) { ui.setupUi(this); startTimer(50); connect(ui.pushButton, &QPushButton::clicked, this, &QtGuiApplication2::showCurrentTime); } void QtGuiApplication2::timerEvent(QTimerEvent *event) { //QThread::msleep(2000);這個和下面的效果是一樣的 QTime qTime1 = QTime::currentTime(); while (qTime1.msecsTo(QTime::currentTime())<2000) qDebug() << "do nothing just for test"; } void QtGuiApplication2::showCurrentTime() { ui.label->setText(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")); }
Ui:
當運行程序的時候,點擊按鈕發現textLabel的響應時間差不多是2秒,通過text顯示的時間可以計算出來
解決方法:
void QtGuiApplication2::timerEvent(QTimerEvent *event) { //QThread::msleep(2000); QTime qTime1 = QTime::currentTime(); while (qTime1.msecsTo(QTime::currentTime()) < 2000) { QCoreApplication::processEvents(QEventLoop::AllEvents, 50); qDebug() << "do nothing just for test"; } }
這個解決了操作耗時的情況,但是當你選擇QThread::msleep(2000);那怎么都會卡了
疑問:
假設當前時刻為0;程序開始運行;100ms時刻,我按下按鈕;此時事件隊列里面應該有QTimerEvent;QTimerEvent;QMousePress這三個事件要處理,按理說Label的時間相應應該是4s左右啊,可能的解釋就是If Qt is unable to deliver the requested number of timer events, it will silently discard some.因此它丟棄了QMousePress之前相同的QTimerEvent
此實驗驗證了這個觀念:
#include <QtWidgets/QDialog> #include <QTime> #include "ui_QtGuiApplication2.h" class QtGuiApplication2 : public QDialog { Q_OBJECT public: QtGuiApplication2(QWidget *parent = Q_NULLPTR); protected: void timerEvent(QTimerEvent *event) override; void showCurrentTime(); private: Ui::QtGuiApplication2Class ui; int id; QTime lastTime; };
QtGuiApplication2::QtGuiApplication2(QWidget *parent) : QDialog(parent) { ui.setupUi(this); startTimer(50); id = startTimer(1000); lastTime = QTime::currentTime(); } void QtGuiApplication2::timerEvent(QTimerEvent *event) { qDebug() << "current timer id: " << event->timerId(); if (event->timerId() == id) { ui.label->setText(QString::number(lastTime.msecsTo(QTime::currentTime()))); lastTime= QTime::currentTime(); } }
通過界面的Label顯示基本都是1014左右;多出來的14毫秒就是執行50msQTimerEvent的輸出語句和 lastTime= QTime::currentTime()的總耗時;
因此可以推測出:
當有個定時器在事件隊列里有很多個QTimerEvent;那么當有另外一個事件A到了,在執行完當前的QTimerEvent之后它會丟棄A之前其他QTimerEvent;直接執行事件A
所以14毫秒就是執行50msQTimerEvent的輸出語句和 lastTime= QTime::currentTime()的總耗時