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. How to catch all events before reaching child widgets at a container widget
Forum Updated to NodeBB v4.3 + New Features

How to catch all events before reaching child widgets at a container widget

Scheduled Pinned Locked Moved General and Desktop
17 Posts 6 Posters 24.5k Views 1 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.
  • F Offline
    F Offline
    fifth
    wrote on last edited by
    #1

    The use case was like below,

    1. There was a container widget with some child widgets
    2. Parent widget should be capable of catching all events before reaching children, and it's up to parent to determine whether children should handle this event or not.
    3. I don't know how many children would be, so event filters can't be the solution, there's no way to install all filters.

    I've learned there's one way to get all events
    [quote]
    subclass QApplication and reimplement notify().

    Qt calls QApplication::notify() to send out an event. Reimplementing this function is the only way to get all the events, before any event filters get the opportunity to look at them.
    [/quote]
    But the difficulty was that, in notify(), I've no idea about if the event is the one sent to that widget or its children, at least not quite easy to get that.

    Any other ideas?
    Thanks in advance.

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Franzk
      wrote on last edited by
      #2

      If the child widgets aren't supposed to catch certain events, explicitly ignore the event in those widgets. The event will then be passed to the parent.

      "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • F Offline
        F Offline
        fifth
        wrote on last edited by
        #3

        That's not the case.
        No children is not supposed to catch certain events, it all depends on some rules managed by parent.

        [quote author="Franzk" date="1294391950"]If the child widgets aren't supposed to catch certain events, explicitly ignore the event in those widgets. The event will then be passed to the parent.[/quote]

        1 Reply Last reply
        0
        • D Offline
          D Offline
          DenisKormalev
          wrote on last edited by
          #4

          fifth, you can build list of all children and compare receiver in notify() with this list. It will be the easiest way for you I think.

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #5

            You get events when children are added, an on this "childEvent":http://doc.qt.nokia.com/4.7/qobject.html#childEvent , you can install an eventFilter. That would give you only the events of the children, not of the whole application.

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • F Offline
              F Offline
              fifth
              wrote on last edited by
              #6

              That sounds interesting.

              Then I can install event filter by recursively monitor childEvent(). Thx.

              [quote author="Gerolf" date="1294395574"]You get events when children are added, an on this "childEvent":http://doc.qt.nokia.com/4.7/qobject.html#childEvent , you can install an eventFilter. That would give you only the events of the children, not of the whole application.[/quote]

              1 Reply Last reply
              0
              • F Offline
                F Offline
                fifth
                wrote on last edited by
                #7

                Yes, that's the easiest way to make it. But I'm afraid of performance issue.

                [quote author="Denis Kormalev" date="1294393216"]fifth, you can build list of all children and compare receiver in notify() with this list. It will be the easiest way for you I think.[/quote]

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  DenisKormalev
                  wrote on last edited by
                  #8

                  fifth, all depends on rate of children adding/removing and their count.

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    goetz
                    wrote on last edited by
                    #9

                    The solutions sound too complicated to me.

                    If you instantiate the widget in the first place, you can get all it's children and install the event filter on it.

                    If some child is added later on, there must be some controlling instance that does the "new MyBlaWidget" and adds it to some layout etc. Have that instance install the event filter too and you're done.

                    http://www.catb.org/~esr/faqs/smart-questions.html

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #10

                      I think Gerolf's solution is not complicated at all. I think it is good design to make the parent widget itself responsible. If you have to handle this for each widget you create as it's child, you're bound to forget it sometime, somewhere, let alone that you are duplicating code. The code for the childEvent is easy enough:

                      @
                      void MyWidget::childEvent(QChildEvent* e)
                      {
                      if (e->child()->isWidgetType()) {
                      if (e->type() == QEvent::ChildAdded) {
                      e->child()->installEventFilter(this);
                      } else if (e->type() == QEvent::ChildRemoved) {
                      e->child()->removeEventFilter(this);
                      }
                      }

                      QWidget::childEvent(e);
                      

                      }
                      @

                      See QObject::childEvent.

                      1 Reply Last reply
                      0
                      • F Offline
                        F Offline
                        fifth
                        wrote on last edited by
                        #11

                        Thanks all.

                        To recursively install filters on every descendant, your code would work well plus below code,

                        @
                        bool MyWidget::eventFilter( QObject* target, QEvent* e )
                        {
                        switch (e->type())
                        {
                        case QEvent::ChildAdded:
                        {
                        QChildEvent* ce = (QChildEvent*)e;
                        ce->child()->installEventFilter(this);
                        }
                        break;

                        case QEvent::ChildRemoved:
                            {
                                QChildEvent* ce = (QChildEvent*)e;
                                ce->child()->removeEventFilter(this);
                            }
                            break;
                        }
                        
                        return QWidget::eventFilter(target, e);
                        

                        }
                        @

                        [quote author="Andre" date="1294516755"]I think Gerolf's solution is not complicated at all. I think it is good design to make the parent widget itself responsible. If you have to handle this for each widget you create as it's child, you're bound to forget it sometime, somewhere, let alone that you are duplicating code. The code for the childEvent is easy enough:

                        @
                        void MyWidget::childEvent(QChildEvent* e)
                        {
                        if (e->child()->isWidgetType()) {
                        if (e->type() == QEvent::ChildAdded) {
                        e->child()->installEventFilter(this);
                        } else if (e->type() == QEvent::ChildRemoved) {
                        e->child()->removeEventFilter(this);
                        }
                        }

                        QWidget::childEvent(e);
                        

                        }
                        @

                        See QObject::childEvent.

                        [/quote]

                        EDIT (Gerolf): added @ tags for code

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          andre
                          wrote on last edited by
                          #12

                          If you need to do it recursively, you still, I think, should only apply the filter to widget type children. Othewise, you'll end up filtering events for all QObjects in the hierarchy. That might have unexpected consequences.

                          1 Reply Last reply
                          0
                          • F Offline
                            F Offline
                            fifth
                            wrote on last edited by
                            #13

                            [quote author="Andre" date="1294651517"]If you need to do it recursively, you still, I think, should only apply the filter to widget type children. Othewise, you'll end up filtering events for all QObjects in the hierarchy. That might have unexpected consequences. [/quote]

                            Sure, thx for reminder.

                            Unfortunately, I was too optimistic.
                            The above code I added looked like not properly working on all descendants.
                            I demoed and found that only first 2 levels of descendant got successfully installed filters. I was wondering where it went wrong.

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              andre
                              wrote on last edited by
                              #14

                              -Well, one issue may be that you are only adding children that are created while they are already added. That may not always be the case. A widget, already containing child widgets, can be added to the hierarchy. If you really want to catch all of those, make sure you also add all existing child widgets of the new child widget being added.-

                              Let me rephrase that, as I find it difficult to understand when I read it back myself:

                              One issue may be that you are only adding an event filter on the the widget (W) that is added as the new child, but not on any child widgets (CC) that new widget (W) may already have when it is added to your container widget (T). Any composite widget (W) will have that problem, and that includes all widgets that contain a scroll bar, a scrollable area, but also for instance the combo box widget is a composite.

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                giesbert
                                wrote on last edited by
                                #15

                                Hi fifth,

                                you also have to take care, that, during ChildAdded / ChildRemoved, you install eventFilters on sub widgets. It might happen, that a widget with sub widgets is added (e.g. a widget with a ui file, a pre layouted widget, ...). That is also not handled by your code...

                                @
                                void MyWidget::addChild(QObject* pObject)
                                {
                                if(pObject && pObject->isWidgetType())
                                {
                                pObject->installEventFilter(this);

                                    const QObjectList& childList = pObject->children();
                                    for(QObjectList::const_iterator it = childList.begin(); it != childList.end(); ++it)
                                    {
                                        addChild(*it);
                                    }
                                }
                                

                                }

                                void MyWidget::removeChild(QObject* pObject)
                                {
                                if(pObject && pObject->isWidgetType())
                                {
                                pObject->removeEventFilter(this);

                                    const QObjectList& childList = pObject->children();
                                    for(QObjectList::const_iterator it = childList.begin(); it != childList.end(); ++it)
                                    {
                                        removeChild(*it);
                                    }
                                }
                                

                                }

                                void MyWidget::childEvent(QChildEvent* e)
                                {
                                if (e->child()->isWidgetType())
                                {
                                if (e->type() == QEvent::ChildAdded)
                                {
                                addChild(e->child());
                                }
                                else if (e->type() == QEvent::ChildRemoved)
                                {
                                removeChild(e->child());
                                }
                                }

                                QWidget::childEvent(e);
                                

                                }

                                bool MyWidget::eventFilter( QObject* target, QEvent* e )
                                {
                                switch (e->type())
                                {
                                case QEvent::ChildAdded:
                                {
                                QChildEvent* ce = (QChildEvent*)e;
                                addChild(ce->child());
                                }
                                break;

                                case QEvent::ChildRemoved:
                                    {
                                        QChildEvent* ce = (QChildEvent*)e;
                                        removeChild(ce->child());
                                    }
                                    break;
                                }
                                
                                return QWidget::eventFilter(target, e);
                                

                                }
                                @

                                This example also includes, that widgets parents are always widgets, so if a child is a non widget, it may not contain widgets as children.

                                Nokia Certified Qt Specialist.
                                Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                                1 Reply Last reply
                                0
                                • F Offline
                                  F Offline
                                  fifth
                                  wrote on last edited by
                                  #16

                                  @Andre,

                                  Got your idea. It's really prone to forget those already existed widgets, like toolbar, scrollbar, etc.

                                  But my demo showed that newly created widgets still failed to get filter installed.

                                  Let's take it more detail.
                                  I built a QFrame-based widget as container widget, then a ScrollArea, its content widget, and simply 2 PushButtons on content widget. Everything was dynamically built while no Qt Designer got involved.

                                  However it proved that container widget was well aware of adding of ScrollArea, content widget, but not those 2 buttons. Weird.

                                  @Gerolf,
                                  I won't need to handle ui files, I will build everything dynamically.

                                  1 Reply Last reply
                                  0
                                  • F Offline
                                    F Offline
                                    fifth
                                    wrote on last edited by
                                    #17

                                    The problem mentioned above I guess that it was something regarding to timing. The timing 2 buttons was created, the timing childEvent was handled, the timing content widget finished its creation.

                                    But Gerolf's code successfully handled everything by going through every child widget.

                                    Thanks all you guys.

                                    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