Updating a QProgressBar from a counter
-
I am trying to create a progress bar that appears only if a very big number is selected, and to make it appear I am using the following:
@ if (number > 10000000)
{
// if the number entered is big, display a progress bar
ui->progressBar->show();
ui->progressBar->setRange(0,number/2);} else { // otherwise keep the progress bar hidden ui->progressBar->hide(); }@
This seems to work fine, however my real problem is that I can't manage to make the progress bar update at every step of my calculations, my program is using a loop of the sort:
@for (counter = 2; counter <= number/2 ; counter++) {
if (number % counter == 0) {
divisibles++;
}@What I would like to do is to update the progress bar at every loop iteration, so that the when "counter" increases, the progress on the progress bar increases.
I tried using connect() but I need a QObject to connect the signal to, and a simple int won't do.Can anyone point me in the right direction?
Thank you
David -
when your loop executes, the CPU does only that, execute the loop (somewhat simplified picture). So there's nothing updating the progress bar graphics. You can give Qt an opportunity to handle other things (signals/slots/GUI-Updates/User-Interaction) with
@qApp->processEvents();@
And maybe a
@ui->progressBar->update();@
before that (Though I think this shouldn't be necessary, because a value change on the progressbar should enqueue that update anyay).Make sure to not call the processEvents at every single loop iteration, because too much time would be spent in this function than in the actual numerical algorithm. Use for example "counter" to make it only execute every n-th iteration, where n could be 1000 for example:
@if (counter % 1000 == 0)
{
ui->progressBar->setValue(counter);
qApp->processEvents();
}@By the way: Like this you can also make your calculation abortable. Make an "Abort" button that sets some variable "aborted" to true when clicked. In the loop, after processEvents, check whether "aborted" returns true, then break out of the loop if so. (Everything that has a progress bar should also come with an abort or cancel button, if you ask me ;))
-
That looks awesome on my window thanks a lot!!
I had to put a progress bar because if the number entered is quite big (above 10 billions) the program could process potentially for 1 minute (also several minutes if the number is above 1000 billions), so I needed a way to show that it was doing progress, and this way I can even implement an "estimated time remaining" thing.Again, thank you :P
-
I agree with DerManu: first fix your algorithm, then considder a progress bar. Also, considder that computers are not created equal. What may take long enough to show a progress bar on your current system, says very little on how much time it takes on the system of your user or the system he might be running your app on in a year or two. So, instead of using a hard cutoff number, make a good estimation of the time to process, and decide to show a progress bar based on that estimation.
Also be aware of the "pitfalls":http://delta.affinix.com/2006/10/23/nested-eventloops/ of processEvents(). Seriously considder using alternatives, like using a worker thread (or better yet, make the algoritm able to run in parallel on multiple cores or processors) or cutting work work up in chunks and doing it one chunck at a time. I've seen it happen in my code, that after long hours of debugging, I ran into a sort of reentrancy problem caused by a processEvents() call.