如何使用Qt创建暂停/等待功能?

时间:2010-09-20 15:07:07

标签: c++ qt sleep wait

我正在玩Qt,我想在两个命令之间创建一个简单的暂停。但是它似乎不允许我使用Sleep(int mili);,我找不到任何明显的等待函数。

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

12 个答案:

答案 0 :(得分:122)

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

我建议您使用此代码而不是睡眠功能,因为它不会让您的GUI冻结。

以下是代码:

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

要将事件延迟n秒 - 请使用addSecs(n)

答案 1 :(得分:56)

从Qt5开始,我们也可以使用

Static Public Members of QThread

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

答案 2 :(得分:31)

小+1到kshark27的答案让它变得动态:

#include <QTime>

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

答案 3 :(得分:29)

previous question使用qSleep()模块中的QtTest提及。为了避免QtTest模块中的开销链接,查看该函数的源代码,您只需创建自己的副本并调用它即可。它使用define来调用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
}

答案 4 :(得分:9)

我们一直在使用以下类 -

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的事件循环进行计时。因此,没有像普通的Windows睡眠功能那样阻止其他事件或UI。

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

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

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

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

答案 5 :(得分:6)

由于您正在尝试“测试某些类代码”,我建议您学习使用QTestLib。它提供了QTest namespaceQtTest module,其中包含许多有用的函数和对象,包括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

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

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

答案 6 :(得分:6)

要使用标准 sleep 功能,请在.cpp文件中添加以下内容:

#include <unistd.h>

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

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

答案 7 :(得分:4)

多年来,我一直在努力让QApplication :: processEvents工作,但是在一些顶级答案中使用了这个问题。 IIRC,如果多个位置最终调用它,它最终可能会导致某些信号无法处理(https://doc.qt.io/archives/qq/qq27-responsive-guis.html)。我通常的首选方案是使用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();
}

答案 8 :(得分:2)

与此处的一些答案类似,但可能更轻一些

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

答案 9 :(得分:1)

如果你想要一个跨平台的方法来做这个,一般模式是从QThread派生并在你的派生类中创建一个函数(静态,如果你愿意的话),它将调用QThread中的一个sleep函数

答案 10 :(得分:1)

由于某种原因,

@kshark27的答案对我不起作用(因为我使用的是Qt 5.7?)所以我最终这样做了:

Visible='<%#  Eval("supportingDocuments") != null %>'

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

答案 11 :(得分:0)

我们可以使用以下方法QT_Delay

QTimer::singleShot(2000,this,SLOT(print_lcd()));

这将等待2秒钟,然后再调用print_lcd()