Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMessageBox::warning replacement that wont process the event loop

QMessageBox::warning replacement that wont process the event loop

Scheduled Pinned Locked Moved Unsolved General and Desktop
40 Posts 9 Posters 4.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S SGaist
    25 May 2022, 19:01

    Hi,

    It just means that they impose a single event loop throughout the whole application lifetime.

    Basically, you should refactor your logic so that you do not depend on the fact that the event loop is processing events.

    Can you explain how you implement your logic ?

    S Offline
    S Offline
    stefanwoe
    wrote on 29 May 2022, 20:39 last edited by stefanwoe
    #23

    @SGaist As noted before - the problem only arises sporadically in not so common situations. I can not "refactor my logic" thanks for that hint. As the SO post shows i am not the only one who has that problem. And problems with event recursion are a common problem id say.

    S 1 Reply Last reply 31 May 2022, 10:19
    0
    • S stefanwoe
      29 May 2022, 20:39

      @SGaist As noted before - the problem only arises sporadically in not so common situations. I can not "refactor my logic" thanks for that hint. As the SO post shows i am not the only one who has that problem. And problems with event recursion are a common problem id say.

      S Offline
      S Offline
      stefanwoe
      wrote on 31 May 2022, 10:19 last edited by
      #24

      @stefanwoe Let me give you a better example: A 3rd party Library we use throws a unexpected exception. We catch this exception and we want to display it (many users just send screenshots instead of logfiles). In some cases the library can not recover from the problem and/or it gets difficult to handle this before it ever had happened. In such a situation the dialog just should "Pause"/Halt the application and display appropriate information - but the application shall not execute any more. We may then i.e. create a Windows Dump file etc. for post mortem analysis before our program possibly will die.

      J 1 Reply Last reply 31 May 2022, 10:27
      0
      • S stefanwoe
        31 May 2022, 10:19

        @stefanwoe Let me give you a better example: A 3rd party Library we use throws a unexpected exception. We catch this exception and we want to display it (many users just send screenshots instead of logfiles). In some cases the library can not recover from the problem and/or it gets difficult to handle this before it ever had happened. In such a situation the dialog just should "Pause"/Halt the application and display appropriate information - but the application shall not execute any more. We may then i.e. create a Windows Dump file etc. for post mortem analysis before our program possibly will die.

        J Online
        J Online
        JonB
        wrote on 31 May 2022, 10:27 last edited by
        #25

        @stefanwoe
        As I understand it. Whether you use exec(), which will create its own event loop, or show(), which will will leave the main event loop running, either way Qt will process new events. And I believe you are saying you want to forbid this while the message box is showing(?).

        Since I see you are Windows, have you considered maybe using a modal native Windows messagebox, which I am hoping would block the Qt event loop while displayed, would that satisfy you requirement?

        S 1 Reply Last reply 31 May 2022, 21:16
        0
        • J JonB
          31 May 2022, 10:27

          @stefanwoe
          As I understand it. Whether you use exec(), which will create its own event loop, or show(), which will will leave the main event loop running, either way Qt will process new events. And I believe you are saying you want to forbid this while the message box is showing(?).

          Since I see you are Windows, have you considered maybe using a modal native Windows messagebox, which I am hoping would block the Qt event loop while displayed, would that satisfy you requirement?

          S Offline
          S Offline
          stefanwoe
          wrote on 31 May 2022, 21:16 last edited by
          #26

          @JonB Yes, i consider writing a Native Dialog for Windows, and one for the Mac. But actually it would be fairly easy to add such a flag to i.e. exec() that forbids the current behavior.
          And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

          J J 2 Replies Last reply 1 Jun 2022, 06:10
          0
          • S stefanwoe
            31 May 2022, 21:16

            @JonB Yes, i consider writing a Native Dialog for Windows, and one for the Mac. But actually it would be fairly easy to add such a flag to i.e. exec() that forbids the current behavior.
            And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

            J Online
            J Online
            JonB
            wrote on 1 Jun 2022, 06:10 last edited by
            #27

            @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

            And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

            It does not seem to solve your issue at all to me. You want a message box to run without Qt processing an event loop and therefore dispatching other events. I say Qt does/can not do that. As @SGaist observed earlier:

            It just means that they impose a single event loop throughout the whole application lifetime.

            So they are just using the single main event loop even when the dialog is showing, instead of the dialog having its own event loop when you call exec(). I do not see any difference wrt your situation. That is my understanding.

            1 Reply Last reply
            0
            • S stefanwoe
              31 May 2022, 21:16

              @JonB Yes, i consider writing a Native Dialog for Windows, and one for the Mac. But actually it would be fairly easy to add such a flag to i.e. exec() that forbids the current behavior.
              And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

              J Offline
              J Offline
              J.Hilk
              Moderators
              wrote on 1 Jun 2022, 06:16 last edited by
              #28

              @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

              And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

              Just like I suggested on the previous page!

              In order to be able to click on any button or even to draw/show the dialog, the event loop has to be processed.

              That is either done by the main event loop or by one QMessagebox is spawning or by one you yourself create. BUT event processing will be happening, if you wan't a responsive UI-window.

              In your case you want only the main event loop to be spinning.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              S J 2 Replies Last reply 1 Jun 2022, 06:21
              0
              • J J.Hilk
                1 Jun 2022, 06:16

                @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

                And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

                Just like I suggested on the previous page!

                In order to be able to click on any button or even to draw/show the dialog, the event loop has to be processed.

                That is either done by the main event loop or by one QMessagebox is spawning or by one you yourself create. BUT event processing will be happening, if you wan't a responsive UI-window.

                In your case you want only the main event loop to be spinning.

                S Offline
                S Offline
                stefanwoe
                wrote on 1 Jun 2022, 06:21 last edited by
                #29

                In your case you want only the main event loop to be spinning.

                How could that be done? Is there a example?

                J 1 Reply Last reply 1 Jun 2022, 06:34
                0
                • S stefanwoe
                  1 Jun 2022, 06:21

                  In your case you want only the main event loop to be spinning.

                  How could that be done? Is there a example?

                  J Offline
                  J Offline
                  J.Hilk
                  Moderators
                  wrote on 1 Jun 2022, 06:34 last edited by J.Hilk 6 Jan 2022, 06:35
                  #30

                  @stefanwoe

                  #ifndef SOMECLASS_H
                  #define SOMECLASS_H
                  
                  #include <QWidget>
                  #include <QMessageBox>
                  
                  
                  class SomeClass : public QWidget
                  {
                      Q_OBJECT
                  public:
                      explicit SomeClass(QWidget *parent = nullptr);
                  
                      void oldBlocking();
                  
                      void newNonBlocking();
                  signals:
                  
                  private slots:
                      void continuationOfnewNonBlocking();
                  
                  private:
                      bool someCondition() {return  rand() % 2;}
                  
                  private:
                      QMessageBox m_messageBox;
                      QMetaObject::Connection m_lastConnect;
                  };
                  
                  #endif // SOMECLASS_H
                  
                  

                  #include "someclass.h"
                  
                  #include <QDebug>
                  
                  SomeClass::SomeClass(QWidget *parent) : QWidget(parent)
                  {
                      m_messageBox.setWindowModality(Qt::ApplicationModal);
                  }
                  
                  void SomeClass::oldBlocking()
                  {
                      if(!someCondition()) {
                          QMessageBox::information(this, "Bla", "blubb");
                      }
                      
                      qDebug() << "Do stuff as normal";
                  }
                  
                  void SomeClass::newNonBlocking()
                  {
                      if(!someCondition()) {
                          m_messageBox.setText("blubb");
                          m_lastConnect = connect(&m_messageBox, &QMessageBox::accepted, this, &SomeClass::continuationOfnewNonBlocking);
                          m_messageBox.show();
                      } else {
                          continuationOfnewNonBlocking();
                      }
                  }
                  
                  void SomeClass::continuationOfnewNonBlocking()
                  {
                      QObject::disconnect(m_lastConnect);
                      qDebug() << "Do stuff as normal";
                  }
                  
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  S 1 Reply Last reply 2 Jun 2022, 08:36
                  0
                  • S Offline
                    S Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 1 Jun 2022, 06:39 last edited by
                    #31

                    Depending on the modality wanted, open makes it window modal.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • J J.Hilk
                      1 Jun 2022, 06:16

                      @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

                      And i still wonder how the approach in the linked Stackoverflow (above) answer would work. this seems to solve the problem.

                      Just like I suggested on the previous page!

                      In order to be able to click on any button or even to draw/show the dialog, the event loop has to be processed.

                      That is either done by the main event loop or by one QMessagebox is spawning or by one you yourself create. BUT event processing will be happening, if you wan't a responsive UI-window.

                      In your case you want only the main event loop to be spinning.

                      J Online
                      J Online
                      JonB
                      wrote on 1 Jun 2022, 06:39 last edited by JonB 6 Jan 2022, 06:41
                      #32

                      @J-Hilk said in QMessageBox::warning replacement that wont process the event loop:

                      In your case you want only the main event loop to be spinning.

                      My understanding is that the OP says he wants/demands no Qt event loop to be running while his dialog is shown, that is the problem....

                      If you read his original report, for example, a window receives an "activate" event for some reason, and he does not want that or any other event to be processed....

                      J 1 Reply Last reply 1 Jun 2022, 06:42
                      0
                      • J JonB
                        1 Jun 2022, 06:39

                        @J-Hilk said in QMessageBox::warning replacement that wont process the event loop:

                        In your case you want only the main event loop to be spinning.

                        My understanding is that the OP says he wants/demands no Qt event loop to be running while his dialog is shown, that is the problem....

                        If you read his original report, for example, a window receives an "activate" event for some reason, and he does not want that or any other event to be processed....

                        J Offline
                        J Offline
                        J.Hilk
                        Moderators
                        wrote on 1 Jun 2022, 06:42 last edited by
                        #33

                        @JonB

                        @J.Hilk said

                        In order to be able to click on any button or even to draw/show the dialog, the event loop has to be processed.

                        That is either done by the main event loop or by one QMessagebox is spawning or by one you yourself create. BUT event processing will be happening, if you wan't a responsive UI-window.

                        @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

                        In your case you want only the main event loop to be spinning.

                        How could that be done? Is there a example?

                        therefore my answer/example


                        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                        Q: What's that?
                        A: It's blue light.
                        Q: What does it do?
                        A: It turns blue.

                        J 1 Reply Last reply 1 Jun 2022, 06:46
                        0
                        • J J.Hilk
                          1 Jun 2022, 06:42

                          @JonB

                          @J.Hilk said

                          In order to be able to click on any button or even to draw/show the dialog, the event loop has to be processed.

                          That is either done by the main event loop or by one QMessagebox is spawning or by one you yourself create. BUT event processing will be happening, if you wan't a responsive UI-window.

                          @stefanwoe said in QMessageBox::warning replacement that wont process the event loop:

                          In your case you want only the main event loop to be spinning.

                          How could that be done? Is there a example?

                          therefore my answer/example

                          J Online
                          J Online
                          JonB
                          wrote on 1 Jun 2022, 06:46 last edited by
                          #34

                          @J-Hilk
                          If you say so! Certainly the OP should try what you have suggested :)

                          1 Reply Last reply
                          1
                          • J J.Hilk
                            1 Jun 2022, 06:34

                            @stefanwoe

                            #ifndef SOMECLASS_H
                            #define SOMECLASS_H
                            
                            #include <QWidget>
                            #include <QMessageBox>
                            
                            
                            class SomeClass : public QWidget
                            {
                                Q_OBJECT
                            public:
                                explicit SomeClass(QWidget *parent = nullptr);
                            
                                void oldBlocking();
                            
                                void newNonBlocking();
                            signals:
                            
                            private slots:
                                void continuationOfnewNonBlocking();
                            
                            private:
                                bool someCondition() {return  rand() % 2;}
                            
                            private:
                                QMessageBox m_messageBox;
                                QMetaObject::Connection m_lastConnect;
                            };
                            
                            #endif // SOMECLASS_H
                            
                            

                            #include "someclass.h"
                            
                            #include <QDebug>
                            
                            SomeClass::SomeClass(QWidget *parent) : QWidget(parent)
                            {
                                m_messageBox.setWindowModality(Qt::ApplicationModal);
                            }
                            
                            void SomeClass::oldBlocking()
                            {
                                if(!someCondition()) {
                                    QMessageBox::information(this, "Bla", "blubb");
                                }
                                
                                qDebug() << "Do stuff as normal";
                            }
                            
                            void SomeClass::newNonBlocking()
                            {
                                if(!someCondition()) {
                                    m_messageBox.setText("blubb");
                                    m_lastConnect = connect(&m_messageBox, &QMessageBox::accepted, this, &SomeClass::continuationOfnewNonBlocking);
                                    m_messageBox.show();
                                } else {
                                    continuationOfnewNonBlocking();
                                }
                            }
                            
                            void SomeClass::continuationOfnewNonBlocking()
                            {
                                QObject::disconnect(m_lastConnect);
                                qDebug() << "Do stuff as normal";
                            }
                            
                            
                            S Offline
                            S Offline
                            stefanwoe
                            wrote on 2 Jun 2022, 08:36 last edited by
                            #35

                            @J-Hilk Thanks very much for your efforts!
                            Unfortunately this does not what i need. If i write

                            SomeClass testMessageBox(this);
                            testMessageBox.newNonBlocking();
                            nextStatement();
                            

                            A Dialog window is shown but code keeps executing nextStatement(); etc. before i have a chance to press any button or even to read the text of the MessageBox as the it disappears when the object "testMessageBox" is destroyed as its scope is left. oldBlocking() behaves like the existing QMessageBox .

                            What i need is a call like

                            testMessageBox.execWithoutProcessingUnrelatedEvents();
                            

                            This call should BLOCK (not nonBlock) execution of further code (it shall not cal nextStatement() as long as the MessageBox is shown) and it should only process events for its own window. From the StackOverflow post this seems possible - but i dont know how to do this.
                            The class you supplied does not do this.

                            1 Reply Last reply
                            0
                            • N Offline
                              N Offline
                              numzero
                              wrote on 19 Jan 2023, 12:57 last edited by
                              #36

                              The OP probably worked around this somehow already but, the issue by itself is still valid.

                              The problem is, this is not well-supported at the OS level. There are some workarounds though:

                              1. Use a helper program. Run it, let it show the message, and wait for it to finish. Should work on any OS.

                              2. On Windows, you can use a thread instead of a program, but only with native UI. Qt UI doesn’t support multithreading. And to my knowledge, on macOS all UI is limited to the main thread.

                              3. Technically, on X11 it is possible to create an additional connection to the display and use that one to show the message. But good luck finding a toolkit that supports that, or showing a readable message without one.

                              4. At least on Windows, it is possible to filter events by window. So e.g. on Windows, you could create a dialog and then run an event loop with GetMessage(&msg, hwnd_your_dialog, 0, 0). This is somewhat fragile but should work. See the docs for GetMessage for details.

                              5. Technically, X11 supports the same. But like in (3) that requires working with raw X11 which is quite different from working with raw WinAPI. I don’t know whether macOS support anything similar.

                              S 1 Reply Last reply 19 Jan 2023, 13:30
                              0
                              • N numzero
                                19 Jan 2023, 12:57

                                The OP probably worked around this somehow already but, the issue by itself is still valid.

                                The problem is, this is not well-supported at the OS level. There are some workarounds though:

                                1. Use a helper program. Run it, let it show the message, and wait for it to finish. Should work on any OS.

                                2. On Windows, you can use a thread instead of a program, but only with native UI. Qt UI doesn’t support multithreading. And to my knowledge, on macOS all UI is limited to the main thread.

                                3. Technically, on X11 it is possible to create an additional connection to the display and use that one to show the message. But good luck finding a toolkit that supports that, or showing a readable message without one.

                                4. At least on Windows, it is possible to filter events by window. So e.g. on Windows, you could create a dialog and then run an event loop with GetMessage(&msg, hwnd_your_dialog, 0, 0). This is somewhat fragile but should work. See the docs for GetMessage for details.

                                5. Technically, X11 supports the same. But like in (3) that requires working with raw X11 which is quite different from working with raw WinAPI. I don’t know whether macOS support anything similar.

                                S Offline
                                S Offline
                                stefanwoe
                                wrote on 19 Jan 2023, 13:30 last edited by
                                #37

                                @numzero No, i did not found a well workaround for that.

                                1 Reply Last reply
                                0
                                • hskoglundH Online
                                  hskoglundH Online
                                  hskoglund
                                  wrote on 19 Jan 2023, 14:14 last edited by
                                  #38

                                  Hi, you could try spinning your own event loop inside SomeClass.
                                  Say you add a QEventLoop instance in the .h file:

                                  ...
                                  private:
                                      QEventloop m_eventLoop;
                                      QMessageBox m_messageBox;
                                      QMetaObject::Connection m_lastConnect;
                                  };
                                  

                                  then in SomeClass.cpp:

                                  ,,,
                                  void SomeClass::newNonBlocking()
                                  {
                                      if(!someCondition()) {
                                          m_messageBox.setText("blubb");
                                          m_lastConnect = connect(&m_messageBox, &QMessageBox::accepted, this, &SomeClass::continuationOfnewNonBlocking);
                                          m_messageBox.show();
                                          m_eventLoop.exec();  // spin here and wait for .exit()
                                      } else {
                                          continuationOfnewNonBlocking();
                                      }
                                  }
                                  
                                  void SomeClass::continuationOfnewNonBlocking()
                                  {
                                      QObject::disconnect(m_lastConnect);
                                      m_eventLoop.exit();
                                      qDebug() << "Do stuff as normal";
                                  }
                                  ```
                                  N S 2 Replies Last reply 19 Jan 2023, 14:23
                                  0
                                  • hskoglundH hskoglund
                                    19 Jan 2023, 14:14

                                    Hi, you could try spinning your own event loop inside SomeClass.
                                    Say you add a QEventLoop instance in the .h file:

                                    ...
                                    private:
                                        QEventloop m_eventLoop;
                                        QMessageBox m_messageBox;
                                        QMetaObject::Connection m_lastConnect;
                                    };
                                    

                                    then in SomeClass.cpp:

                                    ,,,
                                    void SomeClass::newNonBlocking()
                                    {
                                        if(!someCondition()) {
                                            m_messageBox.setText("blubb");
                                            m_lastConnect = connect(&m_messageBox, &QMessageBox::accepted, this, &SomeClass::continuationOfnewNonBlocking);
                                            m_messageBox.show();
                                            m_eventLoop.exec();  // spin here and wait for .exit()
                                        } else {
                                            continuationOfnewNonBlocking();
                                        }
                                    }
                                    
                                    void SomeClass::continuationOfnewNonBlocking()
                                    {
                                        QObject::disconnect(m_lastConnect);
                                        m_eventLoop.exit();
                                        qDebug() << "Do stuff as normal";
                                    }
                                    ```
                                    N Offline
                                    N Offline
                                    numzero
                                    wrote on 19 Jan 2023, 14:23 last edited by
                                    #39

                                    @hskoglund To my knowledge, QEventloop::exec will process all events and not only those related to the message box, and that’s exactly what causes problems for the OP.

                                    1 Reply Last reply
                                    1
                                    • hskoglundH hskoglund
                                      19 Jan 2023, 14:14

                                      Hi, you could try spinning your own event loop inside SomeClass.
                                      Say you add a QEventLoop instance in the .h file:

                                      ...
                                      private:
                                          QEventloop m_eventLoop;
                                          QMessageBox m_messageBox;
                                          QMetaObject::Connection m_lastConnect;
                                      };
                                      

                                      then in SomeClass.cpp:

                                      ,,,
                                      void SomeClass::newNonBlocking()
                                      {
                                          if(!someCondition()) {
                                              m_messageBox.setText("blubb");
                                              m_lastConnect = connect(&m_messageBox, &QMessageBox::accepted, this, &SomeClass::continuationOfnewNonBlocking);
                                              m_messageBox.show();
                                              m_eventLoop.exec();  // spin here and wait for .exit()
                                          } else {
                                              continuationOfnewNonBlocking();
                                          }
                                      }
                                      
                                      void SomeClass::continuationOfnewNonBlocking()
                                      {
                                          QObject::disconnect(m_lastConnect);
                                          m_eventLoop.exit();
                                          qDebug() << "Do stuff as normal";
                                      }
                                      ```
                                      S Offline
                                      S Offline
                                      stefanwoe
                                      wrote on 19 Jan 2023, 14:48 last edited by
                                      #40

                                      @hskoglund I already tried something like that.

                                      1 Reply Last reply
                                      0

                                      • Login

                                      • Login or register to search.
                                      • First post
                                        Last post
                                      0
                                      • Categories
                                      • Recent
                                      • Tags
                                      • Popular
                                      • Users
                                      • Groups
                                      • Search
                                      • Get Qt Extensions
                                      • Unsolved