Results 1 to 4 of 4

Thread: Problems launching a QProgressDialog after main window is made visible

  1. #1
    Join Date
    Jun 2012
    Location
    Spain
    Posts
    16
    Qt products
    Qt4
    Platforms
    Windows

    Default Problems launching a QProgressDialog after main window is made visible

    Hi all,

    I'm developing a desktop (Windows 10) application that needs to perform some very slow initilization (including file search in all local units). For this reason, I want to issue a QProgressDialog just after the main window is visible to inform the user about the progress of the initialization.

    I've been loooking in forums for several days, and this problem seemed to be solved in up to four ways, but I can't it get it with any of the four methods.

    So far, I'm getting my best results by overloading showEvent, and launching my initialization function (just once by using a control variable) inside showEvent after the main window is visible (see option 1 in code below). However, the result is unsatisfactory because, although I can see both the main window and the QProgressDialog, this does not show any motion in the progress bar until a (fake) QMessageBox is issued after the initialization process (please see the pictures below). If the message were not issued, the QProgressDialog would never appear.

    TestInit1-1(show+processEvents).png

    TestInit1-2.jpg

    By the way, is it possible to change the aspect of the bar in the QProgressDialog to make its text invisible, and so the bar will expand to the width of the dialog (just like in Qt Design editor, where setting "textVisible" = false gets this effect)? Or this can be made only by customizing the bar with "setBar"?

    With the other three options proposed in forums I get absolutely worse results, including a Debug error. So, I must be doing something wrong, but I can't guess what. Can anyone teel me what I'm doing wrong, please?

    I attach all the code (MainWindow.h and MainWindow.cpp; I don't think MainWindow.ui is necessary) in case someone may want to test. Note that all four options are implemented (although the three "worse" ones are commented) and can be tested.

    MainWindow.h

    Qt Code:
    1. #include <QDir>
    2. #include <QFile>
    3. #include <QIODevice>
    4. #include <QTextStream>
    5. #include <QProcess>
    6. #include <QStorageInfo>
    7. #include <QTimer>
    8. #include <windows.h>
    9.  
    10. #include <QWidget>
    11. #include <QMessageBox>
    12.  
    13. namespace Ui
    14. {
    15. class MainWindow;
    16. }
    17.  
    18. class MainWindow : public QMainWindow
    19. {
    20. Q_OBJECT
    21.  
    22. protected:
    23. void showEvent(QShowEvent *ev);
    24.  
    25. // Options 1, 2 and 3: Comment signals declaration.
    26. // Option 4: Uncomment signal declaration.
    27. //signals:
    28. // void window_loaded();
    29.  
    30. public:
    31. explicit MainWindow(QWidget *parent = nullptr);
    32. ~MainWindow();
    33.  
    34. private slots:
    35. void on_actionInitializeTestInit();
    36. void on_actionExit_triggered();
    37.  
    38. private:
    39. QLabel* Label1;
    40. QLabel* Label2;
    41. bool TestInit_started;
    42.  
    43. void CreateStatusBar();
    44. void SearchFiles(const QString &start_path, QStringList &File_list);
    45.  
    46. Ui::MainWindow *ui;
    47.  
    48. };
    49.  
    50. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 

    MainWindow.cpp

    Qt Code:
    1. #include <QtGlobal>
    2. #include "MainWindow.h"
    3. #include "ui_MainWindow.h"
    4.  
    5. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
    6. {
    7. ui->setupUi(this);
    8.  
    9. TestInit_started = false;
    10.  
    11. // Options 1, 2 and 3: Comment "connect"
    12. // Option 4: Uncomment "connect" to connect my initialization function to
    13. // a signal which will be issued after showing MainWindow
    14. // connect(this, SIGNAL(MainWindow::window_loaded()), this, SLOT(on_actionInitializeTestInit()), Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
    15.  
    16. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    17.  
    18. // Initialize some internal elements
    19.  
    20. QApplication::restoreOverrideCursor();
    21. }
    22.  
    23. MainWindow::~MainWindow()
    24. {
    25. delete ui;
    26. }
    27.  
    28. void MainWindow::showEvent(QShowEvent *ev)
    29. {
    30. QMainWindow::showEvent(ev);
    31. if (!TestInit_started)
    32. // Option 1: Comment "QMetaObject", "on_action..." and "emit", and
    33. // uncomment "QTimer"
    34. QTimer::singleShot(0, this, SLOT(on_actionInitializeTestInit()));
    35. // Option 2: Comment "QTimer", "on_action..." and "emit", and
    36. // uncomment "QMetaObject"
    37. // RESULT: Debugging error: Dead lock detected in BlockingQueuedConnection: Receiver is MainWindow(0x78fd00)
    38. // QMetaObject::invokeMethod(this, "on_actionInitializeTestInit", Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
    39. // Option 3: Comment "QTimer", "QMetaObject" and "emit", and uncomment
    40. // "on_action..."
    41. // on_actionInitializeTestInit();
    42. // Option 4: Comment "QTimer", "QMetaObject" and "on_action...", and
    43. // uncomment "emit" to issue signal "window_loaded"
    44. // emit MainWindow::window_loaded();
    45. }
    46.  
    47. void MainWindow::on_actionInitializeTestInit()
    48. {
    49. if (TestInit_started) // Yes, this check is written twice. Just in case...
    50. return;
    51.  
    52. TestInit_started = true;
    53.  
    54. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    55.  
    56. // Launch progress dialog. It's configured as a busy indicator because the
    57. // task to perform next is very slow. By the way, is it possible to change
    58. // the aspect of the bar to make its text invisible (just like in the
    59. // Design editor, where setting "textVisible" = false gets), and so the bar
    60. // will expand to the width of the dialog? Or that can be made only by
    61. // customizing the bar with "setBar"?
    62. // Regarding the progress dialog refresh, I've tried with "show", "repaint"
    63. // "update" and "processEvents". If I don't "show", the progress dialog
    64. // doesn't appear; if I don't "processEvents", the progres bar in the
    65. // progress dialog doesn't appear. So, this is my best combination so far.
    66. QProgressDialog progress(this);
    67. // progress.setWindowModality(Qt::WindowModal);
    68. progress.setMinimumWidth(350);
    69. progress.setWindowTitle("Initializing TestInit");
    70. progress.setLabelText("Searching files. This operation may last some minutes. Please wait...");
    71. progress.setCancelButton(nullptr);
    72. progress.setRange(0, 0);
    73. progress.setAutoClose(true);
    74. // progress.setValue(1);
    75. progress.show();
    76. // progress.repaint();
    77. // progress.update();
    78. qApp->processEvents();
    79.  
    80.  
    81.  
    82. // First initialization step: Search in the whole system important files
    83. // for the application. This is a very slow operation, and that's why
    84. // the progress dialog is used as a busy indicator.
    85. // You can customize the file name to search in SearchFiles function below.
    86. QStringList File_list;
    87. foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes())
    88. {
    89. if (storage.isValid() && storage.isReady() && !storage.isReadOnly() &&
    90. ((storage.device().startsWith("\\\\?")) || (storage.device().startsWith("/dev/sda0"))))
    91. {
    92. QString rootpath(QDir::toNativeSeparators(storage.rootPath()));
    93. SearchFiles(rootpath, File_list);
    94. }
    95. }
    96.  
    97.  
    98. // This block is included just for entertainment. After the search, it
    99. // issues an info message showing the files found.
    100. // In the real application this message will not appear. The problem is
    101. // that the progress dialog does not appear until this message is issued.
    102. // Why?
    103. QApplication::restoreOverrideCursor();
    104. QString allfiles;
    105. for (int i = 0; (i < File_list.size()); i++)
    106. {
    107. if (allfiles.size() > 0)
    108. allfiles += '\n';
    109. allfiles += File_list.at(i);
    110. }
    111. QMessageBox::information(this, "Files found", allfiles, QMessageBox::Ok, QMessageBox::Ok);
    112. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    113.  
    114.  
    115. // Other initializations are performed here. These are faster than the
    116. // previous one, and the progress dialog now behaves as usual.
    117. progress.setLabelText("Doing something else (1).");
    118. progress.setRange(0, 1);
    119. progress.setAutoClose(true);
    120. progress.setValue(1);
    121. qApp->processEvents();
    122. // Do something
    123.  
    124. progress.setLabelText("Doing something else (2).");
    125. progress.setValue(1);
    126. qApp->processEvents();
    127. // Do something
    128.  
    129. // And so on...
    130.  
    131. progress.setValue(5);
    132. qApp->processEvents();
    133. progress.close();
    134.  
    135. QApplication::restoreOverrideCursor();
    136. }
    137. void MainWindow::on_actionExit_triggered()
    138. {
    139. close();
    140. }
    141.  
    142. void MainWindow::SearchFiles(const QString &start_path, QStringList &File_list)
    143. {
    144. QString targetfile("config.xml"); // Put here the filename you may want to test
    145. QString iparameters_fich = QDir::toNativeSeparators(start_path + '/' + targetfile);
    146. if (QFile(iparameters_fich).exists())
    147. File_list << iparameters_fich;
    148. else
    149. {
    150.  
    151. // Search configuration files in subdirectories
    152. QStringList nameFilter;
    153. QFileInfoList lstDirectoriesInfo =
    154. QDir(start_path).entryInfoList(nameFilter,
    155. QDir::NoDotAndDotDot | QDir::Dirs,
    156. QDir::Name);
    157. for (int i = 0; (i < lstDirectoriesInfo.size()); i++)
    158. SearchFiles(lstDirectoriesInfo.at(i).absoluteFilePath(), File_list);
    159. }
    160. }
    To copy to clipboard, switch view to plain text mode 


    Regarding the QProgressDialog, I've tried to implement modal and non-modal, and I've also tried with different values: 0, 1 and no value. The result is the same in all cases.

    Thanks a lot in advance. Regards,

    jcbaraza

  2. #2
    Join Date
    Jul 2008
    Posts
    417
    Thanks
    9
    Thanked 54 Times in 52 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Problems launching a QProgressDialog after main window is made visible

    Hi, it might help to add qApp->processEvents(); to your SearchFiles() method. The reason is that both your QProgressDialog and your long search operation take place in GUI thread, and the program does not return to the Qt event loop while your search is running.

    Ginsengelf

  3. #3
    Join Date
    Jun 2012
    Location
    Spain
    Posts
    16
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems launching a QProgressDialog after main window is made visible

    Quote Originally Posted by Ginsengelf View Post
    Hi, it might help to add qApp->processEvents(); to your SearchFiles() method. The reason is that both your QProgressDialog and your long search operation take place in GUI thread, and the program does not return to the Qt event loop while your search is running.

    Ginsengelf
    Wow! That worked! The bar freezes for a while now and then, but now it really looks like working. Thank you so much Gingsengelf!

    And how about my other question regarding the size of the progress bar? Is it possible to make it expand by setting any property, in a similar way as setting "textVisible" = false in Qt Design editor?

  4. #4
    Join Date
    Jun 2012
    Location
    Spain
    Posts
    16
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems launching a QProgressDialog after main window is made visible

    Quote Originally Posted by jcbaraza View Post
    Wow! That worked! The bar freezes for a while now and then, but now it really looks like working. Thank you so much Gingsengelf!

    And how about my other question regarding the size of the progress bar? Is it possible to make it expand by setting any property, in a similar way as setting "textVisible" = false in Qt Design editor?
    I've discovered on my own. The answer is no, but doing is relatively easy. It's something like this:

    Qt Code:
    1. QProgressDialog progress(this);
    2. mybar.setTextVisible(false);
    3. progress.setBar(&mybar);
    To copy to clipboard, switch view to plain text mode 

    And, in case you may need to change the progress display mode from busy indicator to progress bar, you only have to set the text of the progress bar visible again, and change the range:

    Qt Code:
    1. mybar.setTextVisible(true);
    2. progress.setRange(0, n);
    3. progress.setValue(i); // "i" means any value representing the percentage of the task performed so far
    4. // Continue doing tasks and varying Value
    5. // ...
    6. progress.setValue(n);
    7. progress.close();
    To copy to clipboard, switch view to plain text mode 


    Regards,

Similar Threads

  1. Replies: 3
    Last Post: 2nd January 2018, 14:04
  2. launching animated window from already open window
    By krystosan in forum Qt Programming
    Replies: 6
    Last Post: 15th December 2013, 14:06
  3. Problems launching a windows exe from Qt (using QProcess)
    By smacchia in forum Qt Programming
    Replies: 8
    Last Post: 21st March 2012, 11:05
  4. Replies: 2
    Last Post: 17th September 2010, 12:44
  5. Replies: 11
    Last Post: 11th August 2008, 10:14

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.