QProgressDialog in Busy Mode Does Not Update

798 Views Asked by At

I have a simple loop where I'm performing an indeterminate-length operation. I set up a QProgressDialog with range(0,0) to trigger its indeterminate "busy" mode; on my platform, this normally produces a progress bar whose handle bounces back and forth. Even stripped down to the following, though, the dialog appears, responds to the "Cancel" button, but the handle is frozen in place at the end of the bar and doesn't cycle.

    QProgressDialog* progressDialog =
                     new QProgressDialog("My Progress", "Cancel",
                                         0, 0, this);
    progressDialog->setAttribute(Qt::WA_DeleteOnClose, true);
    progressDialog->setModal(true);
    progressDialog->setMinimumDuration(0);
    progressDialog->show();
    progressDialog->setValue(0);
        
    while (!done)
    {
        QThread::msleep(200);
        QCoreApplication::processEvents();
    }

Obviously there's more actually going on inside the loop, but it behaves the same with or without the content; what's left above after commenting out everything else behaves as described.

Why isn't my progress handle bouncing back and forth?

1

There are 1 best solutions below

0
On

Your problem is not a QProgressDialogproblem but instead a threading problem.

Your are running the progress bar and the "job" in the same thread - your GUI thread. What I mean by "job" is all that is inside the loop, and which is considered to be emulate the "busy" mode because it should take a long time in real situation. Thus, when the thread is "busy" while sleeping, your GUI does not move as it is in the same thread.

You should use thread (or QThread) to launch the job to allow the GUI to run in the GUI thread on its own.

Here is an example copied from "all" your code (or almost) and the busy bar indeed is shown correctly.

#include <QApplication>
#include <QProgressDialog>
#include <QThread>

void job()
{
    bool done =true;
    while (!done)
    {
        QThread::msleep(1000);
        QApplication::processEvents();
    }
}

int main(int argc, char *argv[])
{

    bool done = false;
    QApplication a(argc, argv);
    QProgressDialog* progressDialog = new QProgressDialog("My Progress", "Cancel",

                                         0, 0, nullptr);
    progressDialog->setAttribute(Qt::WA_DeleteOnClose, true);
    progressDialog->setModal(true);
    progressDialog->setMinimumDuration(0);
    progressDialog->show();
    progressDialog->setValue(0);

    QThread* thread = QThread::create(job);
    thread->start();

    return a.exec();
}

here is the result of the busy bar (and it moves back and fourth as you wanted )

enter image description here