how do I get the progressbar to not lag and run normally while in a long process?
-
in qt can do like this C# code, I want the progressbar not to lag and the light animation runs as usual, then what kind of code should be made
private void SetProgressBarPosition(ProgressBar progressBar, int position) { bool invokeRequired = progressBar.InvokeRequired; if (invokeRequired) { Form1.SetProgressBarPositionCallBack method = new Form1.SetProgressBarPositionCallBack(this.SetProgressBarPosition); progressBar.Invoke(method, new object[] { progressBar, position }); } else { progressBar.Value = position; } }
-
Hi,
If you have such a long and heavy process, you would usually offload it to a thread and emit a signal from it to update the progress bar.
-
Start with the QThread documentation especially the worker object part.
-
@SGaist Been there, done that RTFM... I just do not see "progress events " - only started and finished .
I have intentionally skipped any such code in my current project - the example is too simplistic.I do not believe that is (good) code example OP asked for.
There is a better , but short , few seconds, Qt example somewhere. Can't recall the name.
Sorry. -
@Blackzero said in how do I get the progressbar to not lag and run normally while in a long process?:
@SGaist I'm new to qt can you give an example of how to use threads, thanks.
Have a look at the Prime Counter example too.
Cheers.
-
First of all, the dirty solution: Call QApplication::processApplication repeatedly to process the update of the progress bar. But, actually don't do it! This solution is way too slow!
For threads you have several options: There is the worker thread solution as already mentioned. You can also use QThread::create with a lambda. There is QMetaObject::invokeMethod which can place work inside an existing thread (just a plain QThread object on which run() has been called which starts the thread's event loop). And there is QtConcurrent::run (and its siblings).
Handling threads directly comes with its pitfalls. 1) You need to make sure that the thread lives long enough (most of the time this means that you do not create the thread object on the stack). 2) If you have a function with a lot of work to be done and only place the middle part into a thread, the function will not wait for the results of the thread (otherwise it would be blocking the main event loop again and you would not see an update of the progress). 3) You cannot call any GUI functions from other threads. You can connect a signal from within your thread to the progress dialog that lives outside your thread and it works, but you cannot just call the functions of the progress dialog. There are workarounds like QMetaObject::invokeMethod to place calls to the progress dialog inside the GUI thread. I have written a small library because this was reoccuring in our project (https://github.com/SimonSchroeder/QtThreadHelper). With this library use
workerThread(...)
with a lambda to start some work in a separate thread andguiThread(...)
with a lambda to place something inside the GUI thread. You can also just have a look at the implementation of guiThread to see how to place calls into the GUI thread.One other note: Do not update the progress dialog too often! We use QTime to start a timer (calling
start()
) before the loop and check forelapsed()
inside the loop. Only if, for example, 50ms have passed we trigger an update of the progress dialog and callrestart()
on the timer. This helps if the loop is too fast.