我正在玩Qt,我想在两个命令之间创建一个简单的暂停。但是,它似乎不允许我使用Sleep(int mili);
,也找不到任何明显的等待功能。
我基本上只是在制作一个控制台应用程序来测试一些类代码,这些类代码随后将包含在适当的Qt GUI中,因此,到目前为止,我无需担心破坏整个事件驱动的模型。
我正在玩Qt,我想在两个命令之间创建一个简单的暂停。但是,它似乎不允许我使用Sleep(int mili);
,也找不到任何明显的等待功能。
我基本上只是在制作一个控制台应用程序来测试一些类代码,这些类代码随后将包含在适当的Qt GUI中,因此,到目前为止,我无需担心破坏整个事件驱动的模型。
QObject().thread()->usleep(1000*1000*seconds);
会睡seconds
几秒钟:)
Answers:
这先前的问题提到使用qSleep()
这是在QtTest
模块。为了避免QtTest
模块中的开销链接,请查看该函数的源代码,然后可以制作自己的副本并进行调用。它使用定义来调用WindowsSleep()
或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中开发的应用程序编写了一个超级简单的延迟函数。
我建议您使用此代码,而不要使用sleep函数,因为它不会使GUI冻结。
这是代码:
void delay()
{
QTime dieTime= QTime::currentTime().addSecs(1);
while (QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
若要将事件延迟n秒,请使用addSecs(n)
。
while
在Qt 5.7中将其放入循环中时,我是唯一经历100%CPU负载的人吗?
currentTime()
和后续currentTime()
调用之间的日期/时间更改而修改了使用此代码运行应用程序的机器的日期/时间,则延迟是错误的。取决于日期/时间更改,延迟要么过期得太早,要么过期太晚(太晚了几秒钟,几分钟,几小时,几天,几个月甚至几年)。延迟/超时使用时钟时间是不行的。
processEvents()
如果没有挂起的事件,该函数将立即返回,这将导致繁忙的循环(占用100%的CPU)。因此,您应该在循环中添加逻辑以等待剩余的100ms循环时间。
delay();
程序中无害外观的语句之后的所有内容。
从Qt5开始,我们还可以使用
void msleep(unsigned long msecs)
void sleep(unsigned long secs)
void usleep(unsigned long usecs)
小+1到kshark27的答案使其动态:
#include <QTime>
void delay( int millisecondsToWait )
{
QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait );
while( QTime::currentTime() < dieTime )
{
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
}
}
#include <QCoreApplication>
也'#包括<QTIME>`
多年来,在尝试使QApplication :: processEvents正常工作时遇到了很多麻烦,就像在一些最佳答案中使用的那样。IIRC,如果多个位置最终调用它,则可能导致某些信号无法处理(https://doc.qt.io/archives/qq/qq27-sensitive-guis.html)。我通常的首选方法是利用QEventLoop(https://doc.qt.io/archives/qq/qq27-sensitive-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();
}
我们一直在使用下面的类-
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旨在协调不同线程之间的互斥体等待。但是使这项工作起作用的原因是wait方法具有超时。以这种方式调用时,它的功能与休眠功能完全相同,但是它使用Qt的事件循环进行计时。因此,没有其他事件或UI被阻止,就像正常的Windows Sleep功能一样。
另外,我们添加了CancelSleep函数,以允许程序的另一部分取消“睡眠”功能。
我们对此感兴趣的是它轻巧,可重用并且完全独立。
QMutex:http://doc.qt.io/archives/4.6/qmutex.html
QWaitCondition:http : //doc.qt.io/archives/4.6/qwaitcondition.html
由于您正在尝试“测试某些类代码”,因此我真的建议您学习使用QTestLib。它提供了一个QTest命名空间和一个QtTest模块,其中包含许多有用的函数和对象,包括QSignalSpy,可用于验证是否发出了某些信号。
由于您最终将与完整的GUI集成,因此使用QTestLib并进行测试而无需睡眠或等待,将为您提供更准确的测试-一种更好地表示真实使用模式的测试。但是,如果您选择不走那条路线,则可以使用QTestLib :: qSleep来完成您所请求的操作。
由于您只需要在启动泵和关闭泵之间稍作停留,因此可以轻松地使用单次计时器:
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()
,如果您有兴趣在命令行中验证几件事,那么肯定会更容易。
编辑:根据评论,这是必需的使用模式。
首先,您需要编辑.pro文件以包含qtestlib:
CONFIG += qtestlib
其次,您需要包括必要的文件:
qSleep
):#include <QTest>
QtTest
模块中的所有项目:#include <QtTest>
。这在功能上等同于为命名空间中存在的每个项目添加一个包含。要使用标准的睡眠功能,请在.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>
然后使用以下睡眠功能之一:
usleep(100);
我们可以使用以下方法QT_Delay
:
QTimer::singleShot(2000,this,SLOT(print_lcd()));
这将等待2秒钟,然后再致电print_lcd()
。
@ kshark27的答案由于某种原因对我不起作用(因为我使用Qt 5.7?),所以我最终这样做:
while (someCondition) {
// do something
QApplication::processEvents();
QThread::sleep(1); // 1 second
};
如果在GUI线程中完成此操作,则显然会在响应用户事件之前引入1秒的GUI延迟。但是,如果可以接受,则该解决方案可能是最容易实现的,甚至Qt也在其“线程基础”文章中对此予以认可(请参阅何时使用线程替代品一节)。
如果您想使用跨平台的方法,通常的模式是从QThread派生并在派生类中创建一个函数(如果需要,可以创建静态函数),该函数将调用QThread中的sleep函数之一。
wait()
或sleep()
完成什么?