Solved How to capture double-click or Ctrl-click on QToolBar
-
I'm converting a legacy application to Qt and our customers expect to be able to double-click and Ctrl-click on a tool bar button to have the tool perform certain special tasks. I've implemented my Qt tool bars using QToolBar and addAction().
So, to capture the MouseDblClickEvent and the MousePressEvent(with modifiers) I'm attempting to use an eventFilter. I first attached the filter to each action. This didn't work. It seems the actions only receive ActionEvent and ShortcutEvent, but certainly not MouseEvent of any kind. I then tried to attach the filter to the QToolBar. However, the QToolBar sees only MouseMove events, and not Press/DblClick.
From what I've read, it seems that addAction() is internally building a widget (QToolButton) to represent and handle the action on the tool bar. This widget is capturing the mouse events and handling most of them. As such, the tool bar itself, as the parent, is not seeing the handled events, and the action is only triggered from the widget.
Is there some way to access this internal widget and thus add an eventFIlter? Is there some other way to accomplish what I'm trying to do?
I have tried using QAction::aasociateWidget() to see if I could gain access to the internal widget, but that's not working. I know that I could manually add all of the actions to the tool bar as QToolButtons myself, thus having access to them, but some of these actions live in a menu and not the toolbar. Does anyone have any other thoughts?
Thanks in advance.
-
Hi,
You can try with findChildren you should be able to get all the buttons in the toolbar.
Hope it helps
-
@SGaist Thanks for the suggestion, findChildren is finding all the buttons, BUT something odd is going on:
My toolbars are customizable so some actions will be on the bar and others will be in a popup menu from a "more" button that I manually add to the bar. The user will (eventually) be able to use a dialog box to move actions from the "more" menu to the bar or vice-versa. I create the entire bar with all actions in Creator. My code then uses the user's last customized state to set the bar up for use. This entails calling QToolBar::clear() to remove all actions, then addAction to put back the ones the user wants on the bar in the order they want. The rest of the actions are added to the "more" menu.
So, when I use findChildren() to search for all of the QToolButton objects on the bar, it finds all of the actions that were on the bar originally. That is, it finds all of the actions that were placed there in Creator before the call to QToolBar::clear(). The result is that the event filter is never called for any of the actions that are on the bar after the clear, but is being called for some of the actions in the "more" menu, i.e. the ones that were not returned to the bar.
It seems that the clear() call is not really removing the QToolButtons from the first set of actions and that new QToolButtons are not being created or added properly, or at least not being correctly attached to the tool bar. Or something?
I seem to recall a thread about something similar a few days ago but never saw the result.
-
OK, so I found the source of my additional problems. I was adding the event filters before adjusting the tool bar contents. Makes sense now facepalm.
Thank you @SGaist for the findChildren<QToolButton*> tip. That is the answer to finding the correct widgets for the eventFilter. Additional note for anyone else who needs this: The list of QToolButton objects in the tool bar contains a few "hidden" buttons. If you don't intend to filter these too, you'll need to ignore them. It appears that checking the QToolButton for a defaultAction() is sufficient to filter these out.
-
It seems that the clear() call is not really removing the QToolButtons from the first set of actions and that new QToolButtons are not being created or added properly, or at least not being correctly attached to the tool bar. Or something?
It removes the actions, and the layout items, it doesn't delete the
QToolButton
instances it seems.
See:
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qtoolbar.cpp#n983
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qtoolbarlayout.cpp#n189
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qtoolbarlayout.cpp#n696
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qtoolbarlayout_p.h#n60
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/kernel/qlayoutitem.h#n119
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/kernel/qlayoutitem.cpp#n284You could try, if you really want to get rid of them, to list the
QToolButton
objects withQObject::findChildren
and delete them manually after you've calledQToolbar::clear
. Seems far fetched, but it might just work.EDIT:
I see we posted at the exact same time. I'm glad you found a solution nonetheless. -
@kshegunov Yes, thanks for your reply. Still useful information to have.
I'm still new to this forum, how do I mark something solved?
(sorry, still a new user so I have to wait 5 minutes before I can post again...)
-
@Mark-A.-Green
Since I gave you 2 stars, no more waiting. You can mark as solved by going to the bottom of the thread and finding the "Topic tools" button. Clicking it will open a menu where you can select the "Mark as solved" button. -
Thank you on both counts. I had seen the button before but the menu was empty. Perhaps the stars helped with that too then :)