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. Adding eventFilter to QAction button does not work
Forum Updated to NodeBB v4.3 + New Features

Adding eventFilter to QAction button does not work

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 2 Posters 837 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.
  • M Offline
    M Offline
    Mike.Greenish
    wrote on last edited by Mike.Greenish
    #1

    I have a QToolBar with QActions inside. I would like to have a text box appear when the user hovers the mouse over one of the buttons. I have created an even filter:

    class ActionButtonHoverHandler : public QObject {
        Q_OBJECT
    public:
        explicit ActionButtonHoverHandler( ParentWindow *p_pw=nullptr ) {
            pParentWindow = p_pw;
        }
    protected:
        bool eventFilter( QObject* obj, QEvent* event ) {
            if( event->type() == QEvent::HoverEnter ) {
                 /* Show text box */
            }
            else if( event->type() == QEvent::HoverLeave ) {
                 /* Hide text box */
            }
            return QObject::eventFilter(obj, event);
        }
    private:
        ParentWindow* pParentWindow
    };
    

    I install the eventHander as follows:

        ActionButtonHoverHandler* af = new ActionButtonHoverHandler( this );
        toolBar()->toolBarButton("actionName")->installEventFilter( af );
    

    toolBar() and toolBarButton are helper functions that retrieve the appropriate ui elements.

    I never fall into "Show text box" or "Hide text box" when I install the event filter on the qaction. If I install it on the QToolBar element, however, the text box is shown and hidden as expected.

    I also tried the following approach:

        QAction* action_button = toolBar()->toolBarButton( "actionName" );
        action_button->activate( QAction::Hover );
        connect( action_button, &QAction::hovered, [=]() {
            /* Show text box */
            }
        });
    

    This works, the text box appears. However, I didn't find an event for when the user's mouse pointer exits the action button to connect to. So method is incomplete as far as I can tell.

    Any suggestions on what might be wrong with approach 1 or how to get an unhovered event for approach 2? Ideas much appreciated !!

    1 Reply Last reply
    0
    • Chris KawaC Online
      Chris KawaC Online
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by Chris Kawa
      #2

      Hi, welcome to the forum.

      Your problem comes from a bit of misunderstanding. A QAction is not a graphical thing. It's not a widget and so you can't hover an action.
      When an action is added to a toolbar a widget (button) is created that triggers that action when clicked. So you can detect a hover on that widget, not on an action. Well, sorta. There's hovered() signal on the QAction, but IMO it's a bad API and only adds to the confusion. It's just a shortcut to save some code, but it really shouldn't be a thing on an action. It's the widget that really is hovered and it only forwards that information to the action. As such it's the widget that gets the HoverEnter and HoverLeave events, not the action.

      Having said that, your toolBarButton function seems to be named badly, as it returns an action, which is not a widget and certainly not a button.
      To retrieve a widget that is created for the action you can use widgetForAction method. Assuming toolbar() returns something QToolBar* derived, to fix your first approach change

      toolBar()->toolBarButton("actionName")->installEventFilter( af );
      

      to

      toolBar()->widgetForAction(toolBar()->toolBarButton("actionName"))->installEventFilter( af );
      

      Your second approach is kinda fixable too, but I think it's not a good idea. As you said this API seems incomplete and even the existing part feels wrong in the first place, so I wouldn't go this route. Another piece to consider is that an action can be tied to multiple different widgets, and this API doesn't tell you which widget was actually hovered, so it's another reason not to use it.

      M 1 Reply Last reply
      2
      • Chris KawaC Chris Kawa

        Hi, welcome to the forum.

        Your problem comes from a bit of misunderstanding. A QAction is not a graphical thing. It's not a widget and so you can't hover an action.
        When an action is added to a toolbar a widget (button) is created that triggers that action when clicked. So you can detect a hover on that widget, not on an action. Well, sorta. There's hovered() signal on the QAction, but IMO it's a bad API and only adds to the confusion. It's just a shortcut to save some code, but it really shouldn't be a thing on an action. It's the widget that really is hovered and it only forwards that information to the action. As such it's the widget that gets the HoverEnter and HoverLeave events, not the action.

        Having said that, your toolBarButton function seems to be named badly, as it returns an action, which is not a widget and certainly not a button.
        To retrieve a widget that is created for the action you can use widgetForAction method. Assuming toolbar() returns something QToolBar* derived, to fix your first approach change

        toolBar()->toolBarButton("actionName")->installEventFilter( af );
        

        to

        toolBar()->widgetForAction(toolBar()->toolBarButton("actionName"))->installEventFilter( af );
        

        Your second approach is kinda fixable too, but I think it's not a good idea. As you said this API seems incomplete and even the existing part feels wrong in the first place, so I wouldn't go this route. Another piece to consider is that an action can be tied to multiple different widgets, and this API doesn't tell you which widget was actually hovered, so it's another reason not to use it.

        M Offline
        M Offline
        Mike.Greenish
        wrote on last edited by
        #3

        @Chris-Kawa Thank you for the explanation, your recommendation worked !

        I'll be honest, it wasn't clear to me whether or not an event could be associated with an action and the hovered() approach only added to my confusion. Actually, I find the menu construction confusing as for me a menu is a graphical element first with actions associated and as structured in QT as far as I can tell, actions have widgets associated with them. I trust that there is some higher theory that escapes me and it is just that I didn't find a clear explanation in the documentation to put me on the correct QT path.

        I kept to the eventFilter which is how I have handled adding event triggered code. For me, the hovered() method is an incomplete kludge and outside of the normal QT way.

        Chris KawaC 1 Reply Last reply
        0
        • M Mike.Greenish

          @Chris-Kawa Thank you for the explanation, your recommendation worked !

          I'll be honest, it wasn't clear to me whether or not an event could be associated with an action and the hovered() approach only added to my confusion. Actually, I find the menu construction confusing as for me a menu is a graphical element first with actions associated and as structured in QT as far as I can tell, actions have widgets associated with them. I trust that there is some higher theory that escapes me and it is just that I didn't find a clear explanation in the documentation to put me on the correct QT path.

          I kept to the eventFilter which is how I have handled adding event triggered code. For me, the hovered() method is an incomplete kludge and outside of the normal QT way.

          Chris KawaC Online
          Chris KawaC Online
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Mike-Greenish said:

          I trust that there is some higher theory that escapes me and it is just that I didn't find a clear explanation in the documentation to put me on the correct QT path.

          It's not that complicated really. It's just that there are two different things here: visual things - menus, menu items, toolbars, buttons, widgets in general, and then there are actions, which are more of an abstract things that can be triggered via one of those visual things or by a shortcut or other means like directly via code.

          The rest are those little shortcuts Qt adds for common cases that kinda muddy the distinction unfortunately. One such common case is that you want an action for every toolbar button so the toolbar has addAction that creates the button and makes the needed connections (not only click but also enabling/disabling). Another common one is that you have a single visual item corresponding to a single action, and thus you get that hovered signal on the action, so you don't have to code that relation by hand every time.

          This is kinda like std::list::sort - it's an algorithm and doesn't really belong in the container class, but because it's such a common operation it's there for convenience, although not fitting the overall stl design very well.

          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