[Solved] How to set a delay ?



  • I want to set a delay inside a for loop, Eg:

    @for(int i=0; i<100; i++)
    {
    doSomething();
    delay(500);
    }@

    I am filling a pixmap like a progress bar, the calculations are done in the paintEvent() , i want to show the progress a with a delay .



  • You put a QThread::msleep() or, if you are on Windows, just a Sleep() there. On Linux you' probably use usleep().

    BUT: This will block the thread, which means no calculations (or UI updates) can be done while sleeping!

    You are much better off by doing the lengthy calculations in a "background" thread and sending progress updates from the background thread to the "main" thread via Signals&Slots, using a queued connection. This allows the UI to update asynchronously and stay fully responsive...

    See also:
    http://qt-project.org/forums/viewthread/21018/



  • One of solution which comes to my mind is local event loop. But it is probably not the best one.
    There is some example of usage "Example":http://qt-project.org/forums/viewthread/19023/
    On this forum I saw some posts about drawback and advantages of such solutions.



  • [quote author="Sam" date="1349950497"]the calculations are done in the paintEvent()[/quote]
    Don't do that. Implementations of paintEvent need to be as fast as possible to keep your application snappy.

    Instead, you should decouple your display of progress with the actual process you're monitoring. Note that implementing a delay is almost never the (right) solution to any programming problem[1]. Instead, just make your application fast. Your users will thank you for it.

    [1] an exception might be software that needs to communicate with hardware where such delays are sometimes unavoidable.



  • instead of a loop you could have a function like this:

    @
    int m_counterForDelayedLoop = 0; //this is a member var
    void loopFunctionWithDelay()
    {
    doSomething();
    if(m_counterForDelayedLoop < 100)
    {
    m_counterForDelayedLoop++;
    QTimer::singleShot(500, this, loopFunctionWithDelay());
    }
    }
    @

    But I think you better follow the suggestions from MuldeR and Andre.



  • If it is only to update the progressbar every so often, why not create a slot to update the progressbar. create a signal that is emitted when you have a doSomething update (e.g. 1% increased).
    This way the GUI is only called 100 times in the entire loop and the operation is as fast as possible. As Andre says it is a very bad programming practice to insert delays or sleep commands. Your on an event driven machine. Not a time / sequential embedded "C" system.
    Greetz



  • Thanks to everyone,

    As suggested by Andre I changed the approach and the calculations are all removed from the paintEvent() and calculated in a seperate function , So in the paintEvent it just draws/fill the pixmap. The requirement of a delay is just for the test , filling of the pixmap will be connected to the process that will be monitored, but that comes from the server.

    The example provided by guziemic did the job

    Thanks for the help



  • Any problem using this function for general delays? I haven't tried it.

    @void QTest::qWait(int ms) [static]@

    Ron


  • Lifetime Qt Champion

    Yes, like the framework name suggests, it's designed for unit testing, not production code.



  • QTest is not compiling for me. I'm using Qt 5.2.1 MinGW 32 bit. When I added @#include <QTest>@ I get "QTest: No such file or directory."

    Then I tried adding:
    INCLUDEPATH += C:/Qt/Qt5.2.1/5.2.1/mingw48_32/include/QtTest
    to my pro file, then I get "expected primary-expression before 'atest'." Any help please?

    @QTest atest; atest.qWait(10);@


  • Moderators

    Like SGaist said, you should not use QTest for general delays. QTest functions are for unit testing.

    You can use QThread::sleep() or QThread::msleep().

    Remember that waiting/sleeping will freeze your thread, which might reduce your program's performance.



  • I got the following to work. Thanks for the help.

    @#include <QThread>
    QThread::msleep(100);@



  • Dear BasicPoke,
    ​you can also use QThread::usleep(5) in a loop till you back-end/other process is not finished. You can use signals\slot to connect. Once your back-end is done you can send signal to handleDBOperatinOnWaitDone(bool ) and do the rest of work. This works fine with multi-threaded application too.

    @
    class ResolutionCalculationBS : public QThread{
    .
    .
    .
    private:
    volatile bool dbOperatinOn;
    .
    .
    .
    };

    void ResolutionCalculationBS::dbOperatinOnWait()
    {
    this->dbOperatinOn = true;
    while (this->dbOperatinOn) {
    QThread::usleep(5);
    }//end while
    return;
    }//end dbOperatinOnWait

    void ResolutionCalculationBS::handleDBOperatinOnWaitDone(bool flag)
    {
    QMutex mutex;
    QMutexLocker locker(&mutex);
    this->dbOperatinOn = flag;
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.