'QT: How to create a simple QProgressDialog object

I want to add a simple QProgressDialog progress dialog to a function called QgsOgrProvider::extent() in qgsogrprovider.cpp of the QGIS project that can have longer calculation times.

When I tried to get this progress dialog widget on display by adding #include <QProgressDialog> to the includes and

QProgressDialog progress(tr("Calculating extent.."), QString(), 0, 100);
progress.setWindowModality(Qt::WindowModal);
progress.setValue(30);
progress.setWindowTitle( tr( "Progress Indication" ) );
progress.setAutoClose( true );
progress.setMinimumDuration( 0 );
progress.setLabelText("Labeltext");

to the function it compiles and links without any problem but when executing the code I only get a black box at the moment when the progress dialog should be shown. enter image description here

According to the QT QDialog description and QObject description I understand that no parent widget necessarily needs to be provided but it would be better to do so as the widget will be positioned in the center to the parent and also it will be destroyed automatically after having finished. In other examples of the QGIS project I have noticed that either a parent is passed, a nullptr or a this object. Why does it not work with a nullptr and how do I find a parent or create a parent that can be passed to the function if necessary?



Solution 1:[1]

I finally found everything out. These are my findings:

  • QProgressDialog can be used without a parent
  • The black widget is filled with content only when progress.setMinimumDuration( 0 ) is followed by a progress.setValue(...) call followed by a QApplication::processEvents() call. This is probably because only the progress.setValue() triggers the widget to be prepared for the output and the QApplication::processEvents() then triggers the final output:
    progress.setMinimumDuration( 0 );
    progress.setValue(...);
    QApplication::processEvents();
  • To use the QProgressDialog with the QGIS main window as parent the widget objectName "QgisApp" can be accessed via qApp->topLevelWidgets() (example taken from QgsGml::getFeatures())

    //find out if there is a QGIS main window. If yes, display a progress dialog
    QProgressDialog *progressDialog = nullptr;
    QWidget *mainWindow = nullptr;
    const QWidgetList topLevelWidgets = qApp->topLevelWidgets();
    for ( QWidgetList::const_iterator it = topLevelWidgets.constBegin(); it != topLevelWidgets.constEnd(); ++it )
    {
      if ( ( *it )->objectName() == QLatin1String( "QgisApp" ) )
      {
        mainWindow = *it;
        break;
      }
    }
    if ( mainWindow )
    {
      progressDialog = new QProgressDialog( ... );
      ...
    }
    

UPDATE:

  • A progress bar keeps black if an initial min value is set again, e.g.
    progressDialog = new QProgressDialog("Calculating .."), "Abort", 0, max);
    progress.setValue(0);
    QApplication::processEvents();
  • progressDialog->show() raises the window even if a minimum duration is set via progressDialog->setMinimumDuration( 2000 ) but the window stays black
  • after the minimumDuration time the progress value must be set in order the progress window to appear
  • when QApplication::processEvents() is called before a value is set the window appears black
  • A progressDialog->setValue(...) is shown black until followed by QApplication::processEvents()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1