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. Why is setting the accept flag of certain QEvents sufficient to cause behaviour?

Why is setting the accept flag of certain QEvents sufficient to cause behaviour?

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 4 Posters 965 Views 3 Watching
  • 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.
  • Y Offline
    Y Offline
    Yuta
    wrote on last edited by
    #1

    Hi forums,

    I understand that in the Qt events system, events are dispatched to appropriate objects by calling their event() function with the relevant QEvent object as a parameter.

    I also understand that these QEvent objects (and all its subclass objects) have an accept flag, which can either be:

    1. set to indicate that the current recipient object will process/handle the event (the event handling will be contained within the recipient object)
    2. cleared to indicate that the current recipient object does not wish to handle the event (therefore the event will be passed on to the current recipient's parent object, and this can go on recursively until the accept flag is set by some object or there are no more parent objects and the event is discarded)

    Therefore, it is my understanding that the purpose of the accept flag of a QEvent is to inform Qt when the propagation chain of a particular event can be terminated.

    Then, it is also my understanding that it is the job of the recipient QObject's event() function (or more specific functions such as mouseMoveEvent() if appropriate) implementations to produce the behaviour that is expected as a response to the event.

    With this in mind, I was confused when I found out that with certain events, like QCloseEvent, the simple act of setting their accept flag is sufficient to cause behaviour (in this case, to close the widget).

    The reason it confuses me is because I thought that the behaviour associated with the closeEvent would be coded within the recipient object's closeEvent() function, and therefore that merely setting the accept flag of the event object would not be sufficient to actually cause the window to close.

    What have I missed here? Are the accept flags of QEvent objects inherently associated with code required to produce behaviour? If so, then what is the purpose of writing "handling" behaviour code within the event functions of the recipient?

    Thanks in advance!

    1 Reply Last reply
    0
    • Y Yuta

      @Pl45m4 Thanks for your reply, and for all your collective patience with my question!

      So let's say that you want to reimplement the QWidget::closeEvent() for your custom window, because you want to handle cases where the QCloseEvent is ignored (e.g. the window contains work that should be saved first). I have seen many examples and tutorials where they reimplement the function in a way similar to below:

      void YourCustomWindow::closeEvent(QCloseEvent * event)
      {
         if (windowCanBeClosed()) {
            // If the window can be closed, close it by calling event->accept()
            event->accept();
         } else {
            // Otherwise, the window should remain open, so call event->ignore()
            event->ignore();
         }
      }
      

      Now, in the above example I understand why calling event->ignore() causes the QCloseEvent to be ignored, and therefore the window to remain open. However, I am confused why simply calling event->accept() leads to the window actually closing. I thought that you would at least need to call the default event handler function (i.e. QWidget::closeEvent() in this case) for the event to be properly handled and produce any behaviour, for example like this:

      void YourCustomWindow::closeEvent(QCloseEvent * event)
      {
         if (windowCanBeClosed()) {
            // If the window can be closed, first accept the event
            event->accept();
            // Then close the window by calling the default event handler
            QWidget::closeEvent(event);
         } else {
            // Otherwise, the window should remain open so ignore the event
            event->ignore();
         }
      }
      

      But apparently, you don't even need to call the base class's default closeEvent() function! All you need to do is just event->accept(). This is why I am confused. Who is actually handling the QCloseEvent by hiding and destroying the window? It seems like the first example of YourCustomWindow::closeEvent() should not do anything, because all it is doing is just calling event->accept() or event->ignore().

      I hope this makes my question clearer– I apologise that I am probably very bad at explaining my question and I thank your patience!

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #6

      @Yuta
      Maybe this will help. It is not the closeEvent() which does the window closing. It is close() which does that. closeEvent() is a notification that handles close being requested.

      [slot]bool QWidget::close()

      Closes this widget. Returns true if the widget was closed; otherwise returns false.

      First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

      Also, this shows why either accept() or calling base QWidget::closeEvent() both accept the event, and allow close() to proceed.

      Pl45m4P 1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        The CloseEvent handling is "reversed". By default the closing shall happen so you have to stop it from happening if that's what you want.

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

        Y 1 Reply Last reply
        3
        • SGaistS SGaist

          Hi,

          The CloseEvent handling is "reversed". By default the closing shall happen so you have to stop it from happening if that's what you want.

          Y Offline
          Y Offline
          Yuta
          wrote on last edited by Yuta
          #3

          @SGaist Hi, thank you for your reply. Yes, I understand that the handling is "reversed" in closeEvents. And I also understand that in most cases, the accept flag of event objects are set by default, and so the default behaviour of a close event is to close the window. But what I am wondering is why, when/if you reimplement closeEvent() functions, all you need to do is event->accept() to close the window. I thought that you would need to write specific handling code within the closeEvent() function to actually close the window, but I am confused because actually no code is required, and all you need is event->accept(). In other words, I thought that the purpose of the accept flags on events was solely to guide the event propagation process, and nothing else. I thought it was the job of event handling functions such as event(), mouseMoveEvent() or closeEvent() to contain code that produces behaviours in response to events. But, in the case of closeEvent(), it seems that the accept flag acutally serves a purpose in producing the actual behaviour of the event (window closing), because all that an implementation of closeEvent() has to do to allow the window to close is to make sure that event->isAccepted() == true. This is where I got confused. Are the accept flags of event objects commonly associated with their actual behaviours within the application that you are building? And in the case of closeEvents, where is the code located which is responsible for actually carrying out the behaviour (i.e. closing the window)?– because it is certainly not directly inside closeEvent() and I am confused. I hope that I am explaining my question clearly...

          Pl45m4P 1 Reply Last reply
          0
          • Y Yuta

            @SGaist Hi, thank you for your reply. Yes, I understand that the handling is "reversed" in closeEvents. And I also understand that in most cases, the accept flag of event objects are set by default, and so the default behaviour of a close event is to close the window. But what I am wondering is why, when/if you reimplement closeEvent() functions, all you need to do is event->accept() to close the window. I thought that you would need to write specific handling code within the closeEvent() function to actually close the window, but I am confused because actually no code is required, and all you need is event->accept(). In other words, I thought that the purpose of the accept flags on events was solely to guide the event propagation process, and nothing else. I thought it was the job of event handling functions such as event(), mouseMoveEvent() or closeEvent() to contain code that produces behaviours in response to events. But, in the case of closeEvent(), it seems that the accept flag acutally serves a purpose in producing the actual behaviour of the event (window closing), because all that an implementation of closeEvent() has to do to allow the window to close is to make sure that event->isAccepted() == true. This is where I got confused. Are the accept flags of event objects commonly associated with their actual behaviours within the application that you are building? And in the case of closeEvents, where is the code located which is responsible for actually carrying out the behaviour (i.e. closing the window)?– because it is certainly not directly inside closeEvent() and I am confused. I hope that I am explaining my question clearly...

            Pl45m4P Offline
            Pl45m4P Offline
            Pl45m4
            wrote on last edited by Pl45m4
            #4

            @Yuta

            Accept in this case does not mean that the accept itself closes the window. It "swallows" the event and signals that the event was handled and can be removed from Event Queue. Then the window will hide and get destroyed (destructed).
            So there is no code to literally close the widget/window in accept, if this is what you thought :)

            QWidget::closeEvent is the event handler for any QWidget. If you don't want the default behavior, you can reimplement it and set your custom handling to your widget.


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            Y 1 Reply Last reply
            0
            • Pl45m4P Pl45m4

              @Yuta

              Accept in this case does not mean that the accept itself closes the window. It "swallows" the event and signals that the event was handled and can be removed from Event Queue. Then the window will hide and get destroyed (destructed).
              So there is no code to literally close the widget/window in accept, if this is what you thought :)

              QWidget::closeEvent is the event handler for any QWidget. If you don't want the default behavior, you can reimplement it and set your custom handling to your widget.

              Y Offline
              Y Offline
              Yuta
              wrote on last edited by Yuta
              #5

              @Pl45m4 Thanks for your reply, and for all your collective patience with my question!

              So let's say that you want to reimplement the QWidget::closeEvent() for your custom window, because you want to handle cases where the QCloseEvent is ignored (e.g. the window contains work that should be saved first). I have seen many examples and tutorials where they reimplement the function in a way similar to below:

              void YourCustomWindow::closeEvent(QCloseEvent * event)
              {
                 if (windowCanBeClosed()) {
                    // If the window can be closed, close it by calling event->accept()
                    event->accept();
                 } else {
                    // Otherwise, the window should remain open, so call event->ignore()
                    event->ignore();
                 }
              }
              

              Now, in the above example I understand why calling event->ignore() causes the QCloseEvent to be ignored, and therefore the window to remain open. However, I am confused why simply calling event->accept() leads to the window actually closing. I thought that you would at least need to call the default event handler function (i.e. QWidget::closeEvent() in this case) for the event to be properly handled and produce any behaviour, for example like this:

              void YourCustomWindow::closeEvent(QCloseEvent * event)
              {
                 if (windowCanBeClosed()) {
                    // If the window can be closed, first accept the event
                    event->accept();
                    // Then close the window by calling the default event handler
                    QWidget::closeEvent(event);
                 } else {
                    // Otherwise, the window should remain open so ignore the event
                    event->ignore();
                 }
              }
              

              But apparently, you don't even need to call the base class's default closeEvent() function! All you need to do is just event->accept(). This is why I am confused. Who is actually handling the QCloseEvent by hiding and destroying the window? It seems like the first example of YourCustomWindow::closeEvent() should not do anything, because all it is doing is just calling event->accept() or event->ignore().

              I hope this makes my question clearer– I apologise that I am probably very bad at explaining my question and I thank your patience!

              JonBJ Pl45m4P 2 Replies Last reply
              0
              • Y Yuta

                @Pl45m4 Thanks for your reply, and for all your collective patience with my question!

                So let's say that you want to reimplement the QWidget::closeEvent() for your custom window, because you want to handle cases where the QCloseEvent is ignored (e.g. the window contains work that should be saved first). I have seen many examples and tutorials where they reimplement the function in a way similar to below:

                void YourCustomWindow::closeEvent(QCloseEvent * event)
                {
                   if (windowCanBeClosed()) {
                      // If the window can be closed, close it by calling event->accept()
                      event->accept();
                   } else {
                      // Otherwise, the window should remain open, so call event->ignore()
                      event->ignore();
                   }
                }
                

                Now, in the above example I understand why calling event->ignore() causes the QCloseEvent to be ignored, and therefore the window to remain open. However, I am confused why simply calling event->accept() leads to the window actually closing. I thought that you would at least need to call the default event handler function (i.e. QWidget::closeEvent() in this case) for the event to be properly handled and produce any behaviour, for example like this:

                void YourCustomWindow::closeEvent(QCloseEvent * event)
                {
                   if (windowCanBeClosed()) {
                      // If the window can be closed, first accept the event
                      event->accept();
                      // Then close the window by calling the default event handler
                      QWidget::closeEvent(event);
                   } else {
                      // Otherwise, the window should remain open so ignore the event
                      event->ignore();
                   }
                }
                

                But apparently, you don't even need to call the base class's default closeEvent() function! All you need to do is just event->accept(). This is why I am confused. Who is actually handling the QCloseEvent by hiding and destroying the window? It seems like the first example of YourCustomWindow::closeEvent() should not do anything, because all it is doing is just calling event->accept() or event->ignore().

                I hope this makes my question clearer– I apologise that I am probably very bad at explaining my question and I thank your patience!

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #6

                @Yuta
                Maybe this will help. It is not the closeEvent() which does the window closing. It is close() which does that. closeEvent() is a notification that handles close being requested.

                [slot]bool QWidget::close()

                Closes this widget. Returns true if the widget was closed; otherwise returns false.

                First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

                Also, this shows why either accept() or calling base QWidget::closeEvent() both accept the event, and allow close() to proceed.

                Pl45m4P 1 Reply Last reply
                1
                • JonBJ JonB

                  @Yuta
                  Maybe this will help. It is not the closeEvent() which does the window closing. It is close() which does that. closeEvent() is a notification that handles close being requested.

                  [slot]bool QWidget::close()

                  Closes this widget. Returns true if the widget was closed; otherwise returns false.

                  First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

                  Also, this shows why either accept() or calling base QWidget::closeEvent() both accept the event, and allow close() to proceed.

                  Pl45m4P Offline
                  Pl45m4P Offline
                  Pl45m4
                  wrote on last edited by
                  #7

                  @JonB said in Why is setting the accept flag of certain QEvents sufficient to cause behaviour?:

                  It is close()

                  Doesn't close() just create a request to close the window (closeEvent)?
                  The window/widget is "closed" using hide + its destructor.


                  If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                  ~E. W. Dijkstra

                  JonBJ Y 2 Replies Last reply
                  0
                  • Pl45m4P Pl45m4

                    @JonB said in Why is setting the accept flag of certain QEvents sufficient to cause behaviour?:

                    It is close()

                    Doesn't close() just create a request to close the window (closeEvent)?
                    The window/widget is "closed" using hide + its destructor.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #8

                    @Pl45m4
                    You may know more than I. I pasted the explanation from QWidget::close(). In either case, it seems to me it is the caller of closeEvent() which does the closing, not closeEvent() itself, which does the closing, which I think is germane to the question @Yuta is asking.

                    1 Reply Last reply
                    1
                    • Y Yuta

                      @Pl45m4 Thanks for your reply, and for all your collective patience with my question!

                      So let's say that you want to reimplement the QWidget::closeEvent() for your custom window, because you want to handle cases where the QCloseEvent is ignored (e.g. the window contains work that should be saved first). I have seen many examples and tutorials where they reimplement the function in a way similar to below:

                      void YourCustomWindow::closeEvent(QCloseEvent * event)
                      {
                         if (windowCanBeClosed()) {
                            // If the window can be closed, close it by calling event->accept()
                            event->accept();
                         } else {
                            // Otherwise, the window should remain open, so call event->ignore()
                            event->ignore();
                         }
                      }
                      

                      Now, in the above example I understand why calling event->ignore() causes the QCloseEvent to be ignored, and therefore the window to remain open. However, I am confused why simply calling event->accept() leads to the window actually closing. I thought that you would at least need to call the default event handler function (i.e. QWidget::closeEvent() in this case) for the event to be properly handled and produce any behaviour, for example like this:

                      void YourCustomWindow::closeEvent(QCloseEvent * event)
                      {
                         if (windowCanBeClosed()) {
                            // If the window can be closed, first accept the event
                            event->accept();
                            // Then close the window by calling the default event handler
                            QWidget::closeEvent(event);
                         } else {
                            // Otherwise, the window should remain open so ignore the event
                            event->ignore();
                         }
                      }
                      

                      But apparently, you don't even need to call the base class's default closeEvent() function! All you need to do is just event->accept(). This is why I am confused. Who is actually handling the QCloseEvent by hiding and destroying the window? It seems like the first example of YourCustomWindow::closeEvent() should not do anything, because all it is doing is just calling event->accept() or event->ignore().

                      I hope this makes my question clearer– I apologise that I am probably very bad at explaining my question and I thank your patience!

                      Pl45m4P Offline
                      Pl45m4P Offline
                      Pl45m4
                      wrote on last edited by Pl45m4
                      #9

                      @Yuta

                      BTW:
                      You should call the base implementation because theoretically you can do anything in your reimplemented closeEvent, even stuff that does not handle the event, but calls some of your functions. After that, you would call the base implementation to keep the default handling (otherwise the window would not close properly)

                      For example:

                      MyWigdet::closeEvent(QCloseEvent *e){
                      
                      // Saves some settings before closing the widget
                      writeToFile();
                      
                      QWidget::closeEvent(e);
                      
                      }
                      

                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      1 Reply Last reply
                      0
                      • Pl45m4P Pl45m4

                        @JonB said in Why is setting the accept flag of certain QEvents sufficient to cause behaviour?:

                        It is close()

                        Doesn't close() just create a request to close the window (closeEvent)?
                        The window/widget is "closed" using hide + its destructor.

                        Y Offline
                        Y Offline
                        Yuta
                        wrote on last edited by
                        #10

                        @JonB and @Pl45m4 thank you for your answers.

                        @Pl45m4 said in Why is setting the accept flag of certain QEvents sufficient to cause behaviour?:

                        The window/widget is "closed" using hide + its destructor.

                        Ah– so then who calls the window's hide() and destructor? In a closeEvent() reimplementation like the one below (which is seen in many example projects, and it works) those functions are not overtly called anywhere.

                        void YourCustomWindow::closeEvent(QCloseEvent * event)
                        {
                           if (windowCanBeClosed()) {
                              event->accept();
                           } else {
                              event->ignore();
                           }
                        }
                        

                        And I suspect it must have something to do with the QCloseEvent object itself, because from the above code we can infer that whether the window will be closed or not depends solely on whether the accept flag of the QCloseEvent is set or cleared.

                        JonBJ 1 Reply Last reply
                        0
                        • Y Yuta

                          @JonB and @Pl45m4 thank you for your answers.

                          @Pl45m4 said in Why is setting the accept flag of certain QEvents sufficient to cause behaviour?:

                          The window/widget is "closed" using hide + its destructor.

                          Ah– so then who calls the window's hide() and destructor? In a closeEvent() reimplementation like the one below (which is seen in many example projects, and it works) those functions are not overtly called anywhere.

                          void YourCustomWindow::closeEvent(QCloseEvent * event)
                          {
                             if (windowCanBeClosed()) {
                                event->accept();
                             } else {
                                event->ignore();
                             }
                          }
                          

                          And I suspect it must have something to do with the QCloseEvent object itself, because from the above code we can infer that whether the window will be closed or not depends solely on whether the accept flag of the QCloseEvent is set or cleared.

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #11

                          @Yuta
                          I have to say: I pasted from QWidget::close() documentation for you, and I think it's pretty clear what is happening. It seems to me it answers the questions you are asking, e.g. the latest post's two questions.

                          Y 1 Reply Last reply
                          2
                          • JonBJ JonB

                            @Yuta
                            I have to say: I pasted from QWidget::close() documentation for you, and I think it's pretty clear what is happening. It seems to me it answers the questions you are asking, e.g. the latest post's two questions.

                            Y Offline
                            Y Offline
                            Yuta
                            wrote on last edited by
                            #12

                            @JonB Apologies! I did read your reply when you first posted it, but I was too thick to understand what you actually meant. I have just re-read it and thought about it– and what you are saying has answered my question! Thank you. I will mark this post as solved.

                            JonBJ 1 Reply Last reply
                            0
                            • Y Yuta

                              @JonB Apologies! I did read your reply when you first posted it, but I was too thick to understand what you actually meant. I have just re-read it and thought about it– and what you are saying has answered my question! Thank you. I will mark this post as solved.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #13

                              @Yuta
                              BTW: for the kind of detail you are looking for, are you aware that even if you do not have the Qt sources/do not compile Qt yourself (e.g. I do not, and do not have the source files). there is a site which has all the Qt source code and allows you to click to navigate on all the code calls?

                              You will find the code for QWidget::close() at https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qwidget.cpp.html#_ZN7QWidget5closeEv It actually just reads:

                              bool QWidget::close()
                              {
                                  return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
                              }
                              

                              so you will have some clicking to do (here just click on close_helper, it's immediately above) if you want to follow what it actually performs :) But if I wanted your level of detail I would at least give it a go!

                              While you are there you will also see the base implementation of QWidget::closeEvent():

                              void QWidget::closeEvent(QCloseEvent *event)
                              {
                                  event->accept();
                              }
                              

                              This is why it doesn't make any difference whether your override calls the base implementation (at least so long as you inherit directly from QWidget, so there is no other possible overriding going on --- if you have a deeper class, I would prefer to call the base just in case it does something else) or just goes event->accept() directly, or both!

                              1 Reply Last reply
                              1

                              • Login

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