如何使用 Qt 创建暂停/等待函数?

发布于 2024-09-24 07:57:36 字数 249 浏览 13 评论 0 原文

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

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

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

仙气飘飘 2024-10-01 07:57:36

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

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

代码如下:

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

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

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

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

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

简单爱 2024-10-01 07:57:36

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

QThread 的静态公共成员

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

From Qt5 onwards we can also use

Static Public Members of QThread

void    msleep(unsigned long msecs)
void    sleep(unsigned long secs)
void    usleep(unsigned long usecs)
纵性 2024-10-01 07:57:36

这个上一个问题提到使用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
}

This previous question mentions using qSleep() which is in the QtTest module. To avoid the overhead linking in the QtTest module, 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().

#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
}
清眉祭 2024-10-01 07:57:36

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

#include <QTime>

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

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

#include <QTime>

void delay( int millisecondsToWait )
{
    QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait );
    while( QTime::currentTime() < dieTime )
    {
        QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
    }
}
迟月 2024-10-01 07:57:36

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

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

inline void delay(int millisecondsWait)
{
    QEventLoop loop;
    QTimer t;
    t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit);
    t.start(millisecondsWait);
    loop.exec();
}
感情废物 2024-10-01 07:57:36

我们一直在使用下面的类 -

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< /a>

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

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.

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

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

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

温柔女人霸气范 2024-10-01 07:57:36

要使用标准 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);

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

#include <unistd.h>

As of Qt version 4.8, the following sleep functions are available:

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:

#include <QThread>

Reference: QThread (via Qt documentation):
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:

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:

#include <QtTest>

And then use one of the sleep functions like so:

usleep(100);
甲如呢乙后呢 2024-10-01 07:57:36

由于您正在尝试“测试一些类代码”,我真的建议学习使用 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

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

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

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

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::qSleep to do what you've requested.

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.

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

First, you need to edit your .pro file to include 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 QtTest module: #include <QtTest>. This is functionally equivalent to adding an include for each item that exists within the namespace.
醉梦枕江山 2024-10-01 07:57:36

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

while (someCondition) {

   // do something

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

};

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

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

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 Basics article (see When to Use Alternatives to Threads section).

甜味拾荒者 2024-10-01 07:57:36

我们可以使用以下方法QT_Delay

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

这将在调用print_lcd()之前等待2秒。

we can use following method QT_Delay:

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

This will wait for 2 seconds before calling print_lcd().

缺⑴份安定 2024-10-01 07:57:36

这在 Qt5 上工作得很好:

void wait( int ms ) {
   QElapsedTimer timer;
   timer.start();

   while ( timer.elapsed() < ms )
       QCoreApplication::processEvents();
}

This work fine with Qt5:

void wait( int ms ) {
   QElapsedTimer timer;
   timer.start();

   while ( timer.elapsed() < ms )
       QCoreApplication::processEvents();
}
甜柠檬 2024-10-01 07:57:36

与这里的一些答案类似,但可能更轻量级

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

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);
    }
}
梦纸 2024-10-01 07:57:36

如果您想要一个跨平台方法来执行此操作,一般模式是从 QThread 派生并在派生类中创建一个函数(如果您愿意,可以是静态函数),该函数将调用 QThread 中的睡眠函数之一。

If you want a cross-platform method of doing this, the general pattern is to derive from QThread and create a function (static, if you'd like) in your derived class that will call one of the sleep functions in QThread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文