PDA

View Full Version : How to use QProgressBar correctly



jshafferman
14th April 2011, 18:04
I am at a lose here on how to achieve what I am trying to do in my current application. Basically what happens is that there is a custom QTreeView that when the user drags and drops and item onto another item, the underlying data is changed and it can take several minutes for the application to move all the data correctly. I am trying to use a QProgressBar to show the user that the data is being moved and that the program is still working just needs some time to process the information.

Here is the code that occurs when a dropEvent happens:



void ClassA::dropEvent(QDropEvent *event)
{
// doing some stuff
emit viewChanged()
}


MainWindow class handles the emitted changed like so...



connect(classA, SIGNAL(viewChanged()), this, SLOT(updateViewChanged()));


The corresponding slot makes some data changes and then a private function inside of this slot does a lot of heavy lifting.



void MainWindow::updateViewChanged()
{
// doing some stuff
// now making call to heavy lifting function
updateData()
}


The updateData() function can take several minutes to update information and what it is doing is changing values in QHash tables and some QLists in order for the information to be written back to the corresponding files correctly. Inside this function there are several loops that are time consuming.


void MainWindow::updateData()
{
QProgress progress(this);
// set min/max appropriately with setMinimum(int) and setMaximum(int)
// set variable called counter to increment the value of progressBar

// nested loops
while()
{
progress.setValue(counter++);

for()
{
progress.setValue(counter++);
for()
{
progress.setValue(counter++);
}
}
}


Basically when this function is called everything happens as should but no progress bar is displayed and I have no clue why. If I add qApp->processEvents() under each progress.setValue() call then the operation takes forever and still no progress bar displayed.

Any suggestions or help would be appreciated because I am not sure how to accomplish what I want to happen. FYI, I know this would make QProgressDialog every time the function is called that won't be the end result but I am just trying to get the darn bar to show!

Thanks for any help!!

falconium
14th April 2011, 21:34
progress.setRange(0,100); ?

SixDegrees
14th April 2011, 22:04
Are you using a QProgressBar or a QProgressDialog? The former needs to be created, placed into a layout and shown before it is visible; the latter provides all that infrastructure for you by placing the progress bar into a dialog.

You probably won't need to call processEvents, but if you do you don't want to call it any more often than is necessary to ensure timely progress bar updates. It's impossible to tell from the code sketch you provided where this should be - it could be just inside the while loop, just inside the outermost for loop, in the innermost for loop, or perhaps when the value of counter modulus some number equals zero. But you certainly don't want to call it every time counter gets incremented.

jshafferman
15th April 2011, 15:10
Thanks SixDegress! I didn't know that you had to place the QProgressBar into the layout before it was visible, this would be the reason I am not seeing it when the application starts the heavy lifting process.

I don't think I need to use processEvents at all but if I wanted to I think if I used it on the outer while loop I would get the intended response. Thank you very much for clearing that up for me! I have used QProgressDialog before so I had assumed they worked the same only one was a dialog with options while the other had no options just the progress bar.

Quick question however, if this is happening in MainWindow (which is sublcass of QMainWindow) do I just add it to the main layout. The MainWindow's central widget is a QSplitter so I am not sure how to do this because I want the progress bar to be centered in the main widget. Thanks for any additional help.

SixDegrees
16th April 2011, 00:50
If you want your progress bar centered on top of the main window, I'd suggest using the QProgressDialog again. Giving it the main window as parent will start it off centered over that widget, and if you want the window blocked you can set it to be modal, or non-modal otherwise.

jshafferman
18th April 2011, 14:28
Thanks I will go ahead and use the QProgressDialog again, is there anyway to hide the buttons on the QProgressDialog? I know I can simply not react to any signal being sent by a click but I am curious if there is a 'hide' option. Thanks again for your help!

jshafferman
21st April 2011, 14:01
I figured out how to remove the cancel button, setCancelButton(0) removes the Cancel button :)