[Qt-interest] the problem of QProgressDialog & QProgressBar

John McClurkin jwm at nei.nih.gov
Wed Jul 15 13:59:38 CEST 2009


John McClurkin wrote:
> Gan Xiebin wrote:
>> Malyushytsky, Alex wrote:
>>  > Because of    p_ShowSysInfoDlg->exec(); I guess.
>>  >
>>  > I don’t think event loop of application is running when you open 
>> another
>>  > modal dialog.
>>  >
>>
>> John McClurkin wrote:
>>  > Alex is correct. calling p_ShowSysInfoDialog->exec() blocks the
>>  > application until it returns. If you want the progress dialog to show
>>  > progress during the execution of the SysInfoDialog, create the 
>> progress
>>  > dialog first on the heap and pass a pointer to the SysInfoDialog
>>  > constructor. Then, in the SysInfoDialog exec function, update the
>>  > progress dialog periodically and call QApplication::processEvents().
>>
>>  > I forgot to add that you show() the progress dialog in the 
>> SysInfoDialog.
>>
>>
>> Thanks Alex and John.
>>
>> OK. The exec() blocks the application until it returns.
>> But although I create the progress dialogue and pass a pointer to the 
>> SysInfoDialog constructor,
>> the GUI thread still blocks while I used wait() in the event loop, 
>> right ?
>> What should I do ?
>> Any reply is welcome. Thanks.
> The worker threads will block, but the GUI thread should not. If all of 
> the time is spent in the worker threads, you can have them send signals 
> at intervals and connect those signals to slots in SysInfoDlg which will 
> then update the progress bar.
Oops this is not correct. In your code, the GUI thread will block on 
thread.wait(). The way to do this is don't call thread.wait(). Connect a 
slot to the thread's finished signal and in that slot set the textLabel 
and close the progress dialog. Also, don't start the threads in 
SysInfoDlg constructor. Write your own exec slot for SysInfoDlg and 
start the threads there. Also, this way you won't need a QTimer because 
the update of the progress dialog will be governed by signals sent from 
the threads.

> 
>>
>> -------------------------------------------------
>> void MainWindow::SysInfoFunc()
>> {
>>
>>     progressDlg = new QProgressDialog("Operation in progress.", 
>> "Cancel", 0, 100, this);
>>        SysInfoDlg *p_ShowSysInfoDlg = new SysInfoDlg(node, progressDlg);
>>     p_ShowSysInfoDlg->exec();
>>
>> }
>>
>> ysInfoDlg::SysInfoDlg(Node *node, QProgressDialog *progressDlg, 
>> QWidget *parent)
>>     : QDialog( parent )
>> {
>>     this->progressDlg = progressDlg;
>>     this->progressDlg->setValue(0);
>>
>>     timer = new QTimer(this);
>>     connect(timer, SIGNAL(timeout()), this, SLOT(performProgressDlg()));
>>     timer->start(1000);
>>
>>     this->progressDlg->show();
>>     QApplication::processEvents();
>>
>> // set text
>>   textLabel = new QLabel();
>>
>>   thread1.start();  // A task
>>   thread2.start();  // Another task
>>
>>   thread1.wait(); // wait for task finished, and set text to the label
>>   thread2.wait(); // like thread1 ...
>>
>>   textLabel->setText( ... );
>>
>> // close dialog
>>     timer->stop();
>>     this->progressDlg->close();
>> }
>>
>> void SysInfoDlg::performProgressDlg()
>> {
>>     if(progressDlg->value() + 1 < progressDlg->maximum())
>>     {
>>         progressDlg->setValue(progressDlg->value() + 1);
>>     }
>>     else
>>     {
>>         timer->stop();
>>         progressDlg->close();
>>     }
>>     progressDlg->show();
>>     QApplication::processEvents();
>> }
>>
>> -------------------------------------------------------------------------------------- 
>>



More information about the Qt-interest-old mailing list