Ich spiele mit Qt herum und möchte eine einfache Pause zwischen zwei Befehlen erstellen. Es scheint mir jedoch nicht zu erlauben Sleep(int mili);
, und ich kann keine offensichtlichen Wartefunktionen finden.
Ich mache im Grunde nur eine Konsolenanwendung, um einen Klassencode zu testen, der später in einer richtigen Qt-GUI enthalten sein wird. Daher mache ich mir vorerst nicht die Mühe, das gesamte ereignisgesteuerte Modell zu beschädigen.
wait()
odersleep()
erreichen?QObject().thread()->usleep(1000*1000*seconds);
wird fürseconds
Sekunden schlafen :)Antworten:
In dieser vorherigen Frage wird erwähnt,
qSleep()
welche imQtTest
Modul enthalten ist. Um die Overhead-Verknüpfung imQtTest
Modul zu vermeiden, können Sie bei der Suche nach der Quelle für diese Funktion einfach eine eigene Kopie erstellen und diese aufrufen. Es verwendet Definitionen, um entweder WindowsSleep()
oder Linux aufzurufennanosleep()
.#ifdef Q_OS_WIN #include <windows.h> // 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 }
quelle
Ich habe eine supereinfache Verzögerungsfunktion für eine Anwendung geschrieben, die ich in Qt entwickelt habe.
Ich würde Ihnen raten, diesen Code anstelle der Sleep-Funktion zu verwenden, da dadurch Ihre GUI nicht einfriert.
Hier ist der Code:
void delay() { QTime dieTime= QTime::currentTime().addSecs(1); while (QTime::currentTime() < dieTime) QCoreApplication::processEvents(QEventLoop::AllEvents, 100); }
Um ein Ereignis um n Sekunden zu verzögern, verwenden Sie
addSecs(n)
.quelle
while
in Qt 5.7 in eine Schleife setzt ?currentTime()
und weiterencurrentTime()
Aufrufen geändert werden . Je nach Änderung von Datum und Uhrzeit läuft die Verzögerung entweder zu früh oder viel zu spät ab (Sekunden, Minuten, Stunden, Tage, Monate oder sogar Jahre zu spät). Die Verwendung der Uhrzeit für Verzögerungen / Timeouts ist kein Problem.processEvents()
Funktion wird sofort zurückgegeben, wenn keine ausstehenden Ereignisse vorliegen, was zu einer Besetztschleife führt (die 100% der CPU beansprucht). Daher sollten Sie der Schleife Logik hinzufügen, um auf den Rest der verbleibenden 100-ms-Schleifenzeit zu warten.delay();
Aussage in Ihrem Programm.Ab Qt5 können wir auch verwenden
Statische öffentliche Mitglieder von QThread
void msleep(unsigned long msecs) void sleep(unsigned long secs) void usleep(unsigned long usecs)
quelle
Kleine +1 auf die Antwort von kshark27 , um es dynamisch zu machen:
#include <QTime> void delay( int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
quelle
#include <QCoreApplication>
auch <QTime> `Ich hatte im Laufe der Jahre große Probleme damit, QApplication :: processEvents zum Laufen zu bringen, wie es in einigen der wichtigsten Antworten verwendet wird. IIRC: Wenn mehrere Standorte es aufrufen, kann dies dazu führen, dass einige Signale nicht verarbeitet werden ( https://doc.qt.io/archives/qq/qq27-responsive-guis.html ). Meine übliche bevorzugte Option ist die Verwendung eines 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(); }
quelle
Wir haben die folgende Klasse verwendet -
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 wurde entwickelt, um das Warten von Mutex zwischen verschiedenen Threads zu koordinieren. Aber was diese Arbeit macht, ist, dass die Wartemethode eine Zeitüberschreitung aufweist. Wenn es auf diese Weise aufgerufen wird, funktioniert es genau wie eine Schlaffunktion, verwendet jedoch die Ereignisschleife von Qt für das Timing. Daher werden keine anderen Ereignisse oder die Benutzeroberfläche blockiert, wie dies bei der normalen Windows-Schlaffunktion der Fall ist.
Als Bonus haben wir die CancelSleep-Funktion hinzugefügt, damit ein anderer Teil des Programms die "Sleep" -Funktion abbrechen kann.
Was uns daran gefallen hat, ist, dass es leicht, wiederverwendbar und völlig eigenständig ist.
QMutex: http://doc.qt.io/archives/4.6/qmutex.html
QWaitCondition: http://doc.qt.io/archives/4.6/qwaitcondition.html
quelle
Da Sie versuchen, "Klassencode zu testen", würde ich wirklich empfehlen, den Umgang mit QTestLib zu lernen . Es bietet einen QTest-Namespace und ein QtTest-Modul , die eine Reihe nützlicher Funktionen und Objekte enthalten, einschließlich QSignalSpy , mit dem Sie überprüfen können, ob bestimmte Signale ausgegeben werden.
Da Sie sich irgendwann in eine vollständige Benutzeroberfläche integrieren werden, erhalten Sie durch die Verwendung von QTestLib und das Testen ohne Schlafen oder Warten einen genaueren Test, der die tatsächlichen Verwendungsmuster besser darstellt. Sollten Sie sich jedoch dafür entscheiden, diesen Weg nicht zu gehen, können Sie QTestLib :: qSleep verwenden , um das zu tun, was Sie angefordert haben.
Da Sie zwischen dem Starten und Abschalten der Pumpe nur eine Pause benötigen, können Sie problemlos einen Timer mit einem Schuss verwenden:
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(); }
Aber es
qSleep()
wäre definitiv einfacher, wenn Sie nur ein paar Dinge in der Befehlszeile überprüfen würden.BEARBEITEN : Basierend auf dem Kommentar sind hier die erforderlichen Verwendungsmuster.
Zuerst müssen Sie Ihre .pro-Datei bearbeiten, um qtestlib einzuschließen:
Zweitens müssen Sie die erforderlichen Dateien einschließen:
qSleep
):#include <QTest>
QtTest
Modul :#include <QtTest>
. Dies entspricht funktional dem Hinzufügen eines Includes für jedes Element, das im Namespace vorhanden ist.quelle
Um die Standard- Schlaffunktion zu verwenden, fügen Sie Folgendes in Ihre CPP-Datei ein:
#include <unistd.h>
Ab Qt Version 4.8 stehen folgende Schlaffunktionen zur Verfügung:
void QThread::msleep(unsigned long msecs) void QThread::sleep(unsigned long secs) void QThread::usleep(unsigned long usecs)
Um sie zu verwenden, fügen Sie einfach Folgendes in Ihre CPP-Datei ein:
#include <QThread>
Referenz: QThread (über die Qt-Dokumentation): http://doc.qt.io/qt-4.8/qthread.html
Andernfalls führen Sie diese Schritte aus ...
Ändern Sie die Projektdatei wie folgt:
Beachten Sie, dass in neueren Versionen von Qt der folgende Fehler angezeigt wird:
... also ändern Sie stattdessen die Projektdatei wie folgt:
Fügen Sie dann in Ihrer CPP-Datei Folgendes hinzu:
#include <QtTest>
Und dann verwenden Sie eine der Schlaffunktionen wie folgt:
usleep(100);
quelle
Wir können folgende Methode verwenden
QT_Delay
:QTimer::singleShot(2000,this,SLOT(print_lcd()));
Dies wird 2 Sekunden warten, bevor Sie anrufen
print_lcd()
.quelle
Ähnlich wie einige Antworten hier, aber vielleicht etwas leichter
void MyClass::sleepFor(qint64 milliseconds){ qint64 timeToExitFunction = QDateTime::currentMSecsSinceEpoch()+milliseconds; while(timeToExitFunction>QDateTime::currentMSecsSinceEpoch()){ QApplication::processEvents(QEventLoop::AllEvents, 100); } }
quelle
Die Antwort von @ kshark27 hat aus irgendeinem Grund bei mir nicht funktioniert (weil ich Qt 5.7 verwende?), also habe ich Folgendes getan:
while (someCondition) { // do something QApplication::processEvents(); QThread::sleep(1); // 1 second };
Wenn dies im GUI-Thread erfolgt, führt dies offensichtlich zu einer Verzögerung von 1 Sekunde, bevor auf Benutzerereignisse reagiert wird. Aber wenn Sie damit leben können, ist diese Lösung wahrscheinlich am einfachsten zu implementieren, und sogar Qt unterstützt sie in ihrem Artikel über Threading-Grundlagen (siehe Abschnitt Wann werden Alternativen zu Threads verwendet ).
quelle
Wenn Sie dazu eine plattformübergreifende Methode wünschen, besteht das allgemeine Muster darin, von QThread abzuleiten und in Ihrer abgeleiteten Klasse eine Funktion (statisch, wenn Sie möchten) zu erstellen, die eine der Sleep-Funktionen in QThread aufruft.
quelle