changing progressbar value few times inside one function
-
Hi, I have a problem with QProgressBar
void MainWindow::on_pushButton_clicked() { QProgressBar *progressBar = new QProgressBar; progressBar->setRange(0, 100); progressBar->setValue(1); progressBar->show(); for (int i = 1; i < 11; i++) { progressBar->setValue(10*i); QThread::msleep(100); } }
I expected this function to increase progressBar value every 0.1sec, but it creates QProgressBar, sleeps a whole second and sets progressBar value instantly to 100.
Detailed description:
I have a function which can last even over a minute, and want to create a QProgressBar for user to know, that program hasn't stopped, and windows not to display a warning "application stopped running. do you want to close it?".
Everything would be nice, if progressBar updated instantly, but it only shows with 0 value till funcion end -
@Corvette653 because I have one ready made.
-
@Corvette653 said in changing progressbar value few times inside one function:
I expected this function to increase progressBar value every 0.1sec, but it creates QProgressBar, sleeps a whole second and sets progressBar value instantly to 100.
Well, it does not work this way - you are blocking Qt event loop with your for loop and msleep()!
If you have a long lasting operation then move it to a thread. In that thread you can emit a signal to tell the UI to update the progress bar (but don't do it in that thread!). -
@jsulm
Could you write a minimal compilable example? -
@Corvette653 said in changing progressbar value few times inside one function:
Could you write a minimal compilable example?
I could. But I will not.
Please start by reading documentation (and examples) to learn how to do it.
https://doc.qt.io/qt-5/qthread.html
https://doc.qt.io/qt-5/signalsandslots.html -
@Corvette653 because I have one ready made.
-
@J-Hilk
Thank you so much, I have analized your project.
I am wondering if there is any sense in making workerObject?
Fourth and fifth solution are beyond my capacity, so I try to choose between workerThread and Thread + workerObject -
Just as others have said before, you need to use threads to have the progress dialog update in real time. One common workaround (so that you don't have to use threads) is to call
QApplication::processEvents()
occasionally. However, this will really slow down your loop by multiple factors and is not advisable for interactive applications.If you use threads you have to make sure that every call to methods of
QProgressBar
is done inside the GUI thread. Otherwise your application will crash. One way to schedule a call inside the GUI event loop is to useQMetaObject::invokeMethod(qApp, ...)
. This can quickly become quite unreadable, especially when you do it over and over again. That is why we wrote a little header-only library to simplify this task: https://github.com/SimonSchroeder/QtThreadHelper. Have a look at Use Case 2 in the description. It will show how to use this tiny library to update the progress. -
@Corvette653 said in changing progressbar value few times inside one function:
@J-Hilk
Thank you so much, I have analized your project.
I am wondering if there is any sense in making workerObject?
Fourth and fifth solution are beyond my capacity, so I try to choose between workerThread and Thread + workerObjectThere are some differences, mostly it's easier to set up and not to mess up. Plus, you can very easily switch between using a thread and mot using a thread by simply not moving the object to the new thread instance.
In the end it's up to you.
-
@J-Hilk
Ok, one more time, thank you so much.Comparing your example with documentation, shouldn't you use finished signal there?
https://github.com/DeiVadder/QtThreadExample/blob/6b28ba239fbbe83b530e5850df279bfe67a64f55/mainwindow.cpp#L106 -
@Corvette653 in this particular case you could do that, it would result in the same outcome
However, if you, in the thread sub class, uncomment the
exec()
, finished will never be emitted on its own -
In my programm, I got
QThread: Destroyed while thread is still running
when I was using operationDone, changing into finished relolved this problem