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
Forum Updated to NodeBB v4.3 + New Features

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.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #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
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on 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

      JonBJ 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        1. AFAIK, yes that's what is expected
        2. I am currently not sure how you could implement that.
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #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
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on 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

          JonBJ 1 Reply Last reply
          0
          • SGaistS SGaist

            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 ?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #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
            • JonBJ JonB

              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 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?

              JonBJ 1 Reply Last reply
              0
              • M MEMekaniske

                @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?

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #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
                0
                • JonBJ JonB

                  @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 last edited by
                  #8

                  @JonB I understand.

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

                  JonBJ 1 Reply Last reply
                  0
                  • M MEMekaniske

                    @JonB I understand.

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

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on 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
                    • JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #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

                      • Login

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