Ricerca…
Osservazioni
QTimer può anche essere utilizzato per richiedere una funzione da eseguire non appena il ciclo degli eventi ha elaborato tutti gli altri eventi in sospeso. Per fare ciò, utilizzare un intervallo di 0 ms.
// option 1: Set the interval to 0 explicitly.
QTimer *timer = new QTimer;
timer->setInterval( 0 );
timer->start();
// option 2: Passing 0 with the start call will set the interval as well.
QTimer *timer = new QTimer;
timer->start( 0 );
// option 3: use QTimer::singleShot with interval 0
QTimer::singleShot(0, [](){
// do something
});
Semplice esempio
L'esempio seguente mostra come utilizzare un QTimer
per chiamare uno slot ogni 1 secondo.
Nell'esempio, utilizziamo un QProgressBar
per aggiornare il suo valore e controllare che il timer QProgressBar
correttamente.
main.cpp
#include <QApplication>
#include "timer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Timer timer;
timer.show();
return app.exec();
}
timer.h
#ifndef TIMER_H
#define TIMER_H
#include <QWidget>
class QProgressBar;
class Timer : public QWidget
{
Q_OBJECT
public:
Timer(QWidget *parent = 0);
public slots:
void updateProgress();
private:
QProgressBar *progressBar;
};
#endif
timer.cpp
#include <QLayout>
#include <QProgressBar>
#include <QTimer>
#include "timer.h"
Timer::Timer(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *layout = new QHBoxLayout();
progressBar = new QProgressBar();
progressBar->setMinimum(0);
progressBar->setMaximum(100);
layout->addWidget(progressBar);
setLayout(layout);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Timer::updateProgress);
timer->start(1000);
setWindowTitle(tr("Timer"));
resize(200, 200);
}
void Timer::updateProgress()
{
progressBar->setValue(progressBar->value()+1);
}
timer.pro
QT += widgets
HEADERS = \
timer.h
SOURCES = \
main.cpp \
timer.cpp
Singleshot Timer con funzione Lambda come slot
Se è richiesto un timer singolo, è silenzioso avere lo slot come funzione lambda nel punto in cui è stato dichiarato il timer:
QTimer::singleShot(1000, []() { /*Code here*/ } );
A causa di questo bug (QTBUG-26406) , questo è il modo è possibile solo dal momento che Qt5.4.
Nelle versioni precedenti di Qt5 deve essere fatto con più codice della piastra della caldaia:
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [=]() {
/*Code here*/
timer->deleteLater();
} );
Usando QTimer per eseguire il codice sul thread principale
void DispatchToMainThread(std::function<void()> callback)
{
// any thread
QTimer* timer = new QTimer();
timer->moveToThread(qApp->thread());
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]()
{
// main thread
callback();
timer->deleteLater();
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
}
Questo è utile quando devi aggiornare un elemento dell'interfaccia utente da un thread. Tieni a mente la durata di tutto ciò che fa riferimento alla richiamata.
DispatchToMainThread([]
{
// main thread
// do UI work here
});
Lo stesso codice potrebbe essere adattato per eseguire codice su qualsiasi thread che esegue il ciclo di eventi Qt, implementando così un semplice meccanismo di invio.
Uso di base
QTimer
aggiunge la funzionalità per avere una funzione / slot specifica chiamata dopo un certo intervallo (ripetutamente o solo una volta).
QTimer
consente quindi a un'applicazione GUI di "controllare" le cose regolarmente o gestire i timeout senza dover avviare manualmente un thread aggiuntivo per questo e fare attenzione alle condizioni di gara, perché il timer verrà gestito nel ciclo dell'evento principale.
Un timer può essere semplicemente usato in questo modo:
QTimer* timer = new QTimer(parent); //create timer with optional parent object
connect(timer,&QTimer::timeout,[this](){ checkProgress(); }); //some function to check something
timer->start(1000); //start with a 1s interval
Il timer attiva il segnale di timeout
quando il tempo è scaduto e questo verrà chiamato nel ciclo dell'evento principale.
QTimer :: singleShot semplice utilizzo
Il QTimer :: singleShot viene utilizzato per chiamare uno slot / lambda in modo asincrono dopo n ms.
La sintassi di base è:
QTimer::singleShot(myTime, myObject, SLOT(myMethodInMyObject()));
con myTime il tempo in ms, myObject l'oggetto che contiene il metodo e myMethodInMyObject lo slot da chiamare
Quindi per esempio se vuoi avere un timer che scrive una riga di debug "ciao!" ogni 5 secondi:
cpp
void MyObject::startHelloWave()
{
QTimer::singleShot(5 * 1000, this, SLOT(helloWave()));
}
void MyObject::helloWave()
{
qDebug() << "hello !";
QTimer::singleShot(5 * 1000, this, SLOT(helloWave()));
}
.hh
class MyObject : public QObject {
Q_OBJECT
...
void startHelloWave();
private slots:
void helloWave();
...
};