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();
    ...
};


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow