Come posso creare una funzione di pausa / attesa usando Qt?

Sto giocando con Qt , e voglio creare una semplice pausa tra due comandi. Comunque non sembrerà permettermi di usare Sleep(int mili); e non riesco a trovare nessuna ovvia funzione di attesa.

Fondamentalmente sto facendo un’applicazione console per testare qualche codice di class che verrà successivamente incluso in un’interfaccia Qt corretta, quindi per ora non mi preoccupo di rompere l’intero modello basato sugli eventi.

Questa domanda precedente menziona l’uso di qSleep() che si trova nel modulo QtTest . Per evitare il sovraccarico del collegamento nel modulo QtTest , guardando la sorgente per quella funzione potresti semplicemente creare la tua copia e chiamarla. Usa definisce per chiamare Windows Sleep() o Linux nanosleep() .

 #ifdef Q_OS_WIN #include  // for Sleep #endif void QTest::qSleep(int ms) { QTEST_ASSERT(ms > 0); #ifdef Q_OS_WIN Sleep(uint(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif } 

Ho scritto una funzione di ritardo super semplice per un’applicazione che ho sviluppato in Qt.

Ti consiglierei di usare questo codice piuttosto che la funzione sleep in quanto non permetterà alla tua GUI di bloccarsi.

Ecco il codice:

 void delay() { QTime dieTime= QTime::currentTime().addSecs(1); while (QTime::currentTime() < dieTime) QCoreApplication::processEvents(QEventLoop::AllEvents, 100); } 

Per ritardare un evento di n secondi - usa addSecs(n) .

Da Qt5 in poi possiamo anche usare

Membri pubblici statici di QThread

 void msleep(unsigned long msecs) void sleep(unsigned long secs) void usleep(unsigned long usecs) 

Piccola risposta da +1 a kshark27 per renderla dynamic:

 #include  void delay( int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } } 

Abbiamo usato la class di sotto –

 class SleepSimulator{ QMutex localMutex; QWaitCondition sleepSimulator; public: SleepSimulator::SleepSimulator() { localMutex.lock(); } void sleep(unsigned long sleepMS) { sleepSimulator.wait(&localMutex, sleepMS); } void CancelSleep() { sleepSimulator.wakeAll(); } }; 

QWaitCondition è progettato per coordinare mutex in attesa tra diversi thread. Ma ciò che rende questo lavoro è il metodo di attesa ha un timeout su di esso. Quando viene chiamato in questo modo, funziona esattamente come una funzione sleep, ma utilizza il ciclo degli eventi di Qt per il cronometraggio. Quindi, nessun altro evento o l’interfaccia utente sono bloccati come fa la normale funzione di sospensione di Windows.

Come bonus, abbiamo aggiunto la funzione CancelSleep per consentire ad un’altra parte del programma di annullare la funzione “sleep”.

Ciò che ci è piaciuto di questo è che è leggero, riutilizzabile ed è completamente autonomo.

QMutex: http://doc.qt.io/archives/4.6/qmutex.html

QWaitCondition: http://doc.qt.io/archives/4.6/qwaitcondition.html

Per utilizzare la funzione di sospensione standard, aggiungi quanto segue nel tuo file .cpp:

 #include  

A partire da Qt versione 4.8, sono disponibili le seguenti funzioni di sospensione:

 void QThread::msleep(unsigned long msecs) void QThread::sleep(unsigned long secs) void QThread::usleep(unsigned long usecs) 

Per utilizzarli, aggiungi semplicemente quanto segue nel tuo file .cpp:

 #include  

Riferimento: QThread (tramite documentazione Qt): http://doc.qt.io/qt-4.8/qthread.html

Altrimenti, esegui questi passaggi …

Modifica il file di progetto come segue:

 CONFIG += qtestlib 

Nota che nelle versioni più recenti di Qt avrai il seguente errore:

 Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead. 

… quindi, modifica invece il file di progetto come segue:

 QT += testlib 

Quindi, nel tuo file .cpp, assicurati di aggiungere quanto segue:

 #include  

E quindi utilizzare una delle funzioni di sonno in questo modo:

 usleep(100); 

Dato che stai provando a “testare un codice di class”, consiglierei davvero di imparare a usare QTestLib . Fornisce uno spazio dei nomi QTest e un modulo QtTest che contengono un numero di funzioni e oggetti utili, tra cui QSignalSpy che è ansible utilizzare per verificare che alcuni segnali vengano emessi.

Dal momento che alla fine si integrerà con un’interfaccia grafica completa, l’utilizzo di QTestLib e il test senza dormire o in attesa ti fornirà un test più accurato, che rappresenta meglio i veri modelli di utilizzo. Ma, se dovessi scegliere di non seguire questa strada, potresti usare QTestLib :: qSleep per fare ciò che hai richiesto.

Dal momento che hai solo bisogno di una pausa tra l’avvio della pompa e lo spegnimento, puoi facilmente utilizzare un timer a scatto singolo:

 class PumpTest: public QObject { Q_OBJECT Pump &pump; public: PumpTest(Pump &pump):pump(pump) {}; public slots: void start() { pump.startpump(); } void stop() { pump.stoppump(); } void stopAndShutdown() { stop(); QCoreApplication::exit(0); } void test() { start(); QTimer::singleShot(1000, this, SLOT(stopAndShutdown)); } }; int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); Pump p; PumpTest t(p); t.test(); return app.exec(); } 

Ma qSleep() sarebbe sicuramente più facile se tutto quello che ti interessa è verificare un paio di cose sulla riga di comando.

MODIFICA : in base al commento, ecco i modelli di utilizzo richiesti.

Innanzitutto, devi modificare il tuo file .pro per includere qtestlib:

 CONFIG += qtestlib 

In secondo luogo, è necessario includere i file necessari:

  • Per lo spazio dei nomi QTest (che include qSleep ): #include
  • Per tutti gli elementi nel modulo QtTest : #include . Ciò è funzionalmente equivalente all’aggiunta di un’inclusione per ogni elemento esistente all’interno dello spazio dei nomi.

Ho avuto molti problemi nel corso degli anni cercando di far funzionare QApplication :: processEvents, come viene usato in alcune delle migliori risposte. IIRC, se più sedi finiscono per chiamarlo, può finire per causare alcuni segnali a non essere elaborati ( https://doc.qt.io/archives/qq/qq27-responsive-guis.html ). La mia solita opzione preferita è utilizzare un QEventLoop ( https://doc.qt.io/archives/qq/qq27-responsive-guis.html#waitinginalocaleventloop ).

 inline void delay(int millisecondsWait) { QEventLoop loop; QTimer t; t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit); t.start(millisecondsWait); loop.exec(); } 

Simile ad alcune risposte qui, ma forse un po ‘più leggero

 void MyClass::sleepFor(qint64 milliseconds){ qint64 timeToExitFunction = QDateTime::currentMSecsSinceEpoch()+milliseconds; while(timeToExitFunction>QDateTime::currentMSecsSinceEpoch()){ QApplication::processEvents(QEventLoop::AllEvents, 100); } } 

Se si desidera un metodo multipiattaforma per fare ciò, lo schema generale è quello di derivare da QThread e creare una funzione (statica, se lo si desidera) nella class derivata che chiamerà una delle funzioni sleep in QThread.

La risposta di @kshark27 non ha funzionato per me per qualche ragione (perché uso Qt 5.7?) quindi ho finito per fare questo:

 while (someCondition) { // do something QApplication::processEvents(); QThread::sleep(1); // 1 second }; 

Se questo è fatto nel thread della GUI, ovviamente introduce un ritardo della GUI di 1 secondo prima di rispondere agli eventi dell’utente. Ma se puoi conviverci, questa soluzione è probabilmente la più semplice da implementare e anche Qt lo approva nel loro articolo sulle basi di threading (vedi la sezione Quando usare le alternative ai thread ).