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. Qt::Popup window behaviour
Servers for Qt installer are currently down

Qt::Popup window behaviour

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 4.9k 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.
  • J Offline
    J Offline
    JonB
    wrote on 5 Jun 2020, 15:43 last edited by JonB 6 May 2020, 15:45
    #1

    I have a QPushButton with an associated QWidget window, which pops up temporarily (when the button is clicked) to allow user to interact with some widgets on it. The bare essentials are:

    class PushButtonWithPopup : public QPushButton
    {
        Q_OBJECT
    public:
        PushButtonWithPopup(QWidget *parent = nullptr);
    
    private:
        QWidget _popup;
    
    private slots:
        void doPopup();
    };
    
    
    PushButtonWithPopup::PushButtonWithPopup(QWidget *parent /*= nullptr*/) :
        QPushButton(parent)
    {
        // popup window flags (popup with no frame)
        _popup.setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
    
        // connect button click to execute the popup
        connect(this, &QPushButton::clicked, this, &PushButtonWithPopup::doPopup);
    }
    
    /*slot*/ void PushButtonWithPopup::doPopup()
    {
        // show the popup
        _popup.show();
    }
    
    1. This works splendiferously. When I click anywhere outside the popup it goes away, which is just want I want. But now I'm thinking to myself: https://doc.qt.io/qt-5/qt.html#WindowType-enum for Qt::Popup doesn't actually say it will dismiss on click-outside, so is it supposed to do what I see it doing? Am I unable to see the wood for the trees, what's actually going on?

    2. The click outside which dismisses it --- say, on another widget where its assocaited QPushButton lives --- gets "eaten" to dismiss the popup. I am finding I would actually prefer it if that click caused the popup to dismiss and then proceeded as usual to do its action, instead of being consumed. For example, if I click on some checkbox outside the popup, after the popup disappears I'd like that checkbox to toggle as usual. How would I go about achieving this, where is my click getting eaten?

    M 1 Reply Last reply 8 Jun 2020, 07:13
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 5 Jun 2020, 19:00 last edited by
      #2

      Hi,

      1. AFAIK, yes that's what is expected
      2. I am currently not sure how you could implement that.

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

      J 1 Reply Last reply 6 Jun 2020, 08:26
      1
      • S SGaist
        5 Jun 2020, 19:00

        Hi,

        1. AFAIK, yes that's what is expected
        2. I am currently not sure how you could implement that.
        J Offline
        J Offline
        JonB
        wrote on 6 Jun 2020, 08:26 last edited by JonB 6 Aug 2020, 08:28
        #3

        @SGaist
        Firstly, thank you for answering a question with an answer, not another question ;-)

        Secondly I have some strange Qt behaviour to report on this. I'd really appreciate if you/someone could comment/clarify what might be going on...

        This relates just to my Question #1, how a popup window gets destroyed or not.

        In my own case, the QWidget with setWindowFlags(Qt::Popup) is a member variable allocated on the stack, the class has QWidget _popup; as shown. Consequently I do not expect to leak, and valgrind reports no leak. So far, so good.

        However, a learned colleague here ( @mrjj) allocates these on the heap, so he would have QWidget *_popup and go _popup = new QWidget. He now wonders whether he is consequently leaking? So I changed my stuff over to investigate, and come up with "inexplicable" results:

        For my existing popup, I change to:

        QWidget *_popup;
        _popup = new QWidget;
        connect(_popup, &QObject::destroyed, []() { qDebug() << "Destroyed"; });
        _popup->setWindowFlags(Qt::Popup);
        ...
        _popup->show();
        
        • valgrind (which works for me, Linux) does not report this as a leak on program exit. Yet I do not ever see the "Destroyed" message on QObject::destroyed.
        • I now create an extra QWidget *_popup2. I new it, connect() it, but do not set Qt::Popup. I test, and sure enough valgrind does report leak.
        • I now add just _popup2->setWindowFlags(Qt::Popup);, so it has popup flag too. I do not popup2->show() it any time. Now valgrind does not report it leaking; yet "Destroyed" message on QObject::destroyed is still not called.

        Summary:

        • Putting Qt::Popup attribute on a newed widget (without parent) causes it not to leak, even if it is never shown. However, QObject::destroyed is never called.

        • If we assume for a moment that it is being deleted/destroyed somehow, behind-the-scenes code seems to know to delete it if it was newed onto the heap but not (at least, doesn't go wrong) if it is on the stack.

        Very, very simple, minimal:

        #include <QApplication>
        #include <QWidget>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            QWidget w;
        
            // valgrind: next line *DOES* leak
            QWidget *w1 = new QWidget;
            // valgrind: next line does *NOT* leak, because of the line below it
            // and yet if you `connect(w2, &QObject::destroyed)` that does not get called
            QWidget *w2 = new QWidget;
            w2->setWindowFlags(Qt::Popup);
        
            w.show();
            return a.exec();
        }
        

        Explanation, please?

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 8 Jun 2020, 06:01 last edited by
          #4

          AFAIK, the Popup window flag has no influence with regard to any memory management (and it would not make sense as well).

          Do you have suppression files for Valgrind concerning Qt ?

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

          J 1 Reply Last reply 8 Jun 2020, 07:06
          0
          • S SGaist
            8 Jun 2020, 06:01

            AFAIK, the Popup window flag has no influence with regard to any memory management (and it would not make sense as well).

            Do you have suppression files for Valgrind concerning Qt ?

            J Offline
            J Offline
            JonB
            wrote on 8 Jun 2020, 07:06 last edited by JonB 6 Aug 2020, 07:10
            #5

            @SGaist said in Qt::Popup window behaviour:

            AFAIK, the Popup window flag has no influence with regard to any memory management (and it would not make sense as well).

            Hence my question. Nonetheless, the code above behaves as I have documented. Qt 5.12.2, Ubuntu 19.04.

            I have an absolutely vanilla install of Ubuntu valgrind, 3.14.0. I assume there is nothing Qt about it..

            Do you have the opportunity to test that 10 line code yourself? I would also summon @mrjj and request he test under Linux/Windows, since he is the one who is dynamically allocating (my own code the popup widget is on the stack) and would be affected.

            1 Reply Last reply
            0
            • J JonB
              5 Jun 2020, 15:43

              I have a QPushButton with an associated QWidget window, which pops up temporarily (when the button is clicked) to allow user to interact with some widgets on it. The bare essentials are:

              class PushButtonWithPopup : public QPushButton
              {
                  Q_OBJECT
              public:
                  PushButtonWithPopup(QWidget *parent = nullptr);
              
              private:
                  QWidget _popup;
              
              private slots:
                  void doPopup();
              };
              
              
              PushButtonWithPopup::PushButtonWithPopup(QWidget *parent /*= nullptr*/) :
                  QPushButton(parent)
              {
                  // popup window flags (popup with no frame)
                  _popup.setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
              
                  // connect button click to execute the popup
                  connect(this, &QPushButton::clicked, this, &PushButtonWithPopup::doPopup);
              }
              
              /*slot*/ void PushButtonWithPopup::doPopup()
              {
                  // show the popup
                  _popup.show();
              }
              
              1. This works splendiferously. When I click anywhere outside the popup it goes away, which is just want I want. But now I'm thinking to myself: https://doc.qt.io/qt-5/qt.html#WindowType-enum for Qt::Popup doesn't actually say it will dismiss on click-outside, so is it supposed to do what I see it doing? Am I unable to see the wood for the trees, what's actually going on?

              2. The click outside which dismisses it --- say, on another widget where its assocaited QPushButton lives --- gets "eaten" to dismiss the popup. I am finding I would actually prefer it if that click caused the popup to dismiss and then proceeded as usual to do its action, instead of being consumed. For example, if I click on some checkbox outside the popup, after the popup disappears I'd like that checkbox to toggle as usual. How would I go about achieving this, where is my click getting eaten?

              M Offline
              M Offline
              MEMekaniske
              wrote on 8 Jun 2020, 07:13 last edited by
              #6

              @JonB , regarding question 2, A time consuming way to do it would be to track the position of widgets and cursor clicks, but would work I think?

              J 1 Reply Last reply 8 Jun 2020, 07:17
              0
              • M MEMekaniske
                8 Jun 2020, 07:13

                @JonB , regarding question 2, A time consuming way to do it would be to track the position of widgets and cursor clicks, but would work I think?

                J Offline
                J Offline
                JonB
                wrote on 8 Jun 2020, 07:17 last edited by JonB 6 Aug 2020, 07:18
                #7

                @MEMekaniske
                I can't afford to do that, I would need a generic solution. I am guessing I would need to know where Qt code "eats" this and do something about it, perhaps in some eventFilter?

                At the moment I want to resolve what is going on in #1, before I even think of addressing #2!

                M 1 Reply Last reply 8 Jun 2020, 07:29
                0
                • J JonB
                  8 Jun 2020, 07:17

                  @MEMekaniske
                  I can't afford to do that, I would need a generic solution. I am guessing I would need to know where Qt code "eats" this and do something about it, perhaps in some eventFilter?

                  At the moment I want to resolve what is going on in #1, before I even think of addressing #2!

                  M Offline
                  M Offline
                  MEMekaniske
                  wrote on 8 Jun 2020, 07:29 last edited by
                  #8

                  @JonB I understand.

                  Eventfilter would probably do :) HoverMove might be a friend!

                  J 1 Reply Last reply 8 Jun 2020, 07:49
                  0
                  • M MEMekaniske
                    8 Jun 2020, 07:29

                    @JonB I understand.

                    Eventfilter would probably do :) HoverMove might be a friend!

                    J Offline
                    J Offline
                    JonB
                    wrote on 8 Jun 2020, 07:49 last edited by
                    #9

                    @MEMekaniske
                    In trying to investigate #1 yesterday, I had a look through woboq. I believe I came across code for Qt::Popup flag (list of popped up widgets created from it), which did something like accept a mouse event when a popup was visible, and dismiss the popup. I would need to have a look for that again as the best way forward, I think.

                    Meanwhile, however, I am going on strike! Until I have an explanation for the valgrind non-leak-on-newed-Qt::Popup-flag behaviour, I am judging this area as "black magic" and hence too scary to tamper with...

                    1 Reply Last reply
                    1
                    • J Offline
                      J Offline
                      JonB
                      wrote on 8 Jun 2020, 08:44 last edited by JonB 6 Aug 2020, 09:01
                      #10

                      STOP PRESS
                      [Including for @SGaist, @mrjj's attention.]
                      I revisited my 10 line program apparently showing leak on plain new QWidget but not on new QWidget; setWindowFlags(Qt::Popup);.

                      • If I remove the "test" non-Popup widget and only have the Popup widget then valgrind does report the Popup as a leak.
                      • If I reverse the order so that the Popup widget is new-ed first and the non-Popup is new-ed next, then valgrind does report the Popup widget as leaking but the non-Popup widget is not reported as leaking.

                      For whatever reason, this reveals that valgrind sometimes only reports certain leaks but not others [has anyone else encountered this behaviour?]. This is "disappointing", but at least makes sense, showing nothing special about Popup.

                      So going back to @mrjj's situation. I do not leak because my Popup widget is on the stack. In his situation he news on the heap, and I conclude that he does need to delete the Popup window.

                      Problem #1 at least apparently resolved!

                      1 Reply Last reply
                      0

                      1/10

                      5 Jun 2020, 15:43

                      • Login

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