如何使用Qt创build暂停/等待function?

我正在玩Qt ,我想在两个命令之间创build一个简单的停顿。 但是,似乎不让我使用Sleep(int mili); ,我找不到任何明显的等待function。

我基本上只是做一个控制台应用程序来testing一些类的代码,这些代码稍后将包含在一个合适的Qt GUI中,所以现在我不打扰整个事件驱动模型。

这个前面的问题提到使用QtTest模块中的QtTest qSleep() 。 为了避免QtTest模块中的开销链接,查看该函数的源代码,您可以制作自己的副本并调用它。 它使用定义来调用Windows Sleep()或Linux nanosleep()

 #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 } 

我为在Qt中开发的应用程序编写了一个超级简单的延迟函数。

我build议你使用这个代码而不是睡眠函数,因为它不会让你的GUI冻结。

这里是代码:

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

要延迟一个事件n秒 – 使用addSecs(n)

对kshark27的答案小1使其dynamic:

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

从Qt5起,我们也可以使用

QThread的静态公共成员

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

我们一直在使用下面的课程 –

 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旨在协调不同线程之间的互斥等待。 但是什么使得这个工作是等待方法有一个超时。 当以这种方式调用时,它的function与睡眠函数完全相同,但它使用Qt的事件循环来进行计时。 所以,没有其他事件或UI像正常的Windows睡眠function那样被阻塞。

作为奖励,我们添加了CancelSleep函数来允许程序的另一部分取消“睡眠”function。

我们喜欢的是它轻巧,可重复使用,完全独立。

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

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

既然你试图“testing一些类的代码”,我真的build议学习使用QTestLib 。 它提供了一个QTest命名空间和一个QtTest模块 ,其中包含许多有用的函数和对象,包括QSignalSpy ,您可以使用它来validation某些信号是否被发射。

既然你最终将整合GUI,使用QTestLib和testing没有睡觉或等待会给你一个更准确的testing – 一个更好地代表了真正的使用模式。 但是,如果你select不走那条路线,你可以使用QTestLib :: qSleep来完成你所要求的。

由于您只需在启动泵和closures泵之间暂停一下,就可以轻松使用单次计时器:

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

但是如果你感兴趣的话, qSleep()肯定会更容易在命令行上validation一些事情。

编辑 :根据评论,这是所需的使用模式。

首先,你需要编辑你的.pro文件来包含qtestlib:

 CONFIG += qtestlib 

其次,你需要包含必要的文件:

  • 对于QTest命名空间(包括qSleep ): #include <QTest>
  • 对于QtTest模块中的所有项目: #include <QtTest> 。 这在function上等价于为名称空间中存在的每个项目添加一个include。

要使用标准睡眠function,请在.cpp文件中添加以下内容:

 #include <unistd.h> 

从Qt版本4.8开始,可以使用以下睡眠函数:

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

要使用它们,只需在.cpp文件中添加以下内容:

 #include <QThread> 

参考:QThread(通过Qt文档): http : //doc.qt.io/qt-4.8/qthread.html

否则,执行这些步骤…

修改项目文件如下:

 CONFIG += qtestlib 

请注意,在较新版本的Qt中,您将看到以下错误:

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

…所以,而是修改项目文件,如下所示:

 QT += testlib 

然后,在.cpp文件中,一定要添加以下内容:

 #include <QtTest> 

然后使用其中一个睡眠function,如下所示:

 usleep(100); 

类似于这里的一些答案,但也许更轻量一点

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

如果你想要一个跨平台的方法,一般的模式是从QThread派生,并在派生类中创build一个函数(如果你愿意的话),它将调用QThread中的一个睡眠函数。

@ kshark27的答案由于某种原因不适用于我(因为我使用Qt 5.7),所以我最终这样做了:

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

这是在GUI线程中完成的,显然这会在响应用户事件之前引入1秒的GUI延迟。 但是,如果你能忍受它,这个解决scheme可能是最容易实现的,甚至Qt也会在他们的Threading Basics文章中看到它(参见何时使用线程替代方法部分)。

多年来,我在尝试使QApplication :: processEvents正常工作时遇到了很多麻烦,正如一些顶级答案中所使用的。 IIRC,如果多个位置最终调用它,可能会导致一些信号不被处理( https://doc.qt.io/archives/qq/qq27-responsive-guis.html )。 我通常喜欢的select是使用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(); }