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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3752742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:37:46  来源:igfitidea点击:

How do I create a pause/wait function using Qt?

c++qtsleepwait

提问by Zac

I'm playing around with Qt, and I want to create a simple pause between two commands. However it won't seem to let me use Sleep(int mili);, and I can't find any obvious wait functions.

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

I am basically just making a console application to test some class code which will later be included in a proper Qt GUI, so for now I'm not bothered about breaking the whole event-driven model.

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

采纳答案by Arnold Spence

This previous questionmentions using qSleep()which is in the QtTestmodule. To avoid the overhead linking in the QtTestmodule, looking at the source for that function you could just make your own copy and call it. It uses defines to call either Windows Sleep()or Linux nanosleep().

先前的问题提到使用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
}

回答by Kartik Sharma

I wrote a super simple delay function for an application I developed in Qt.

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

I would advise you to use this code rather than the sleep function as it won't let your GUI freeze.

我建议您使用此代码而不是 sleep 函数,因为它不会让您的 GUI 冻结。

Here is the code:

这是代码:

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

To delay an event by n seconds - use addSecs(n).

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

回答by Yash

From Qt5 onwards we can also use

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

Static Public Members of QThread

QThread 的静态公共成员

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

回答by GraehamF

Small +1 to kshark27's answer to make it dynamic:

小 +1 kshark27的答案,使其动态:

#include <QTime>

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

回答by photo_tom

We've been using the below class -

我们一直在使用以下课程 -

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 is designed to coordinate mutex waiting between different threads. But what makes this work is the wait method has a timeout on it. When called this way, it functions exactly like a sleep function, but it uses Qt's event loop for the timing. So, no other events or the UI are blocked like normal windows sleep function does.

QWaitCondition 旨在协调不同线程之间的互斥等待。但是使这项工作起作用的是等待方法有一个超时。以这种方式调用时,它的功能与睡眠函数完全相同,但它使用 Qt 的事件循环进行计时。因此,没有其他事件或 UI 像正常的 Windows 睡眠功能那样被阻止。

As a bonus, we added the CancelSleep function to allows another part of the program to cancel the "sleep" function.

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

What we liked about this is that it lightweight, reusable and is completely self contained.

我们喜欢它的地方在于它轻巧、可重复使用并且完全独立。

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

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

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

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

回答by dvntehn00bz

I've had a lot of trouble over the years trying to get QApplication::processEvents to work, as is used in some of the top answers. IIRC, if multiple locations end up calling it, it can end up causing some signals to not get processed (https://doc.qt.io/archives/qq/qq27-responsive-guis.html). My usual preferred option is to utilize a QEventLoop (https://doc.qt.io/archives/qq/qq27-responsive-guis.html#waitinginalocaleventloop).

多年来,我在尝试让 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();
}

回答by Kaleb Pederson

Since you're trying to "test some class code," I'd really recommend learning to use QTestLib. It provides a QTest namespaceand a QtTest modulethat contain a number of useful functions and objects, including QSignalSpythat you can use to verify that certain signals are emitted.

由于您正在尝试“测试一些类代码”,因此我真的建议您学习使用QTestLib。它提供了一个QTest 命名空间和一个QtTest 模块,其中包含许多有用的函数和对象,包括可用于验证某些信号是否被发出的QSignalSpy

Since you will eventually be integrating with a full GUI, using QTestLib and testing without sleeping or waiting will give you a more accurate test -- one that better represents the true usage patterns. But, should you choose not to go that route, you could use QTestLib::qSleepto do what you've requested.

由于您最终将与完整的 GUI 集成,因此使用 QTestLib 并在不休眠或等待的情况下进行测试将为您提供更准确的测试——更能代表真实使用模式的测试。但是,如果您选择不走这条路,您可以使用QTestLib::qSleep来完成您的要求。

Since you just need a pause between starting your pump and shutting it down, you could easily use a single shot timer:

由于您只需要在启动泵和关闭泵之间暂停,您可以轻松使用单次计时器:

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

But qSleep()would definitely be easier if all you're interested in is verifying a couple of things on the command line.

但是qSleep(),如果您感兴趣的只是在命令行上验证一些事情,那肯定会更容易。

EDIT: Based on the comment, here's the required usage patterns.

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

First, you need to edit your .pro file to include qtestlib:

首先,您需要编辑 .pro 文件以包含 qtestlib:

CONFIG += qtestlib

Second, you need to include the necessary files:

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

  • For the QTest namespace (which includes qSleep): #include <QTest>
  • For all the items in the QtTestmodule: #include <QtTest>. This is functionally equivalent to adding an include for each item that exists within the namespace.
  • 对于 QTest 命名空间(包括qSleep):#include <QTest>
  • 对于QtTest模块中的所有项目:#include <QtTest>. 这在功能上等同于为命名空间中存在的每个项目添加一个包含。

回答by Richard Nalezynski

To use the standard sleepfunction add the following in your .cpp file:

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

#include <unistd.h>

As of Qt version 4.8, the following sleepfunctions are available:

从 Qt 4.8 版开始,可以使用以下睡眠功能:

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

To use them, simply add the following in your .cpp file:

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

#include <QThread>

Reference: QThread (via Qt documentation): http://doc.qt.io/qt-4.8/qthread.html

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

Otherwise, perform these steps...

否则,请执行这些步骤...

Modify the project file as follows:

修改工程文件如下:

CONFIG += qtestlib

Note that in newer versions of Qt you will get the following error:

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

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

... so, instead modify the project file as follows:

...所以,改为按如下方式修改项目文件:

QT += testlib

Then, in your .cpp file, be sure to add the following:

然后,在您的 .cpp 文件中,确保添加以下内容:

#include <QtTest>

And then use one of the sleep functions like so:

然后使用其中一种睡眠功能,如下所示:

usleep(100);

回答by Neurotransmitter

@kshark27's answer didn't work for me for some reason (because I use Qt 5.7?) so I ended up doing this:

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

while (someCondition) {

   // do something

   QApplication::processEvents();
   QThread::sleep(1); // 1 second

};

If this is done in the GUI thread, it obviously introduces a 1 second GUI lag before responding to user events. But if you can live with it, this solution is probably an easiest to implement and even Qt endorses it in their Threading Basicsarticle (see When to Use Alternatives to Threadssection).

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

回答by hytromo

Similar to some answers here, but maybe a little more lightweight

类似于这里的一些答案,但可能更轻巧

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