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

后端 未结 12 2091
执笔经年
执笔经年 2020-11-27 15:19

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

相关标签:
12条回答
  • 2020-11-27 16:11

    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)
    
    0 讨论(0)
  • 2020-11-27 16:13

    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
    }
    
    0 讨论(0)
  • 2020-11-27 16:16

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

    0 讨论(0)
  • 2020-11-27 16:17

    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

    0 讨论(0)
  • 2020-11-27 16:18

    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();
    }
    
    0 讨论(0)
  • 2020-11-27 16:24

    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.
    0 讨论(0)
提交回复
热议问题