Qt World Summit: Register Today!

How to get the event source of a QMenu which is bind to some QPushButtons?

  • I shared a QMenu between some QPushbutton, it's very simple to make the QPushbutton to a menu button. Now I want to adjust the menu according to the button when it's about to show, but how could i know which button fire the menu?

    Thanks for your time.

  • have a look at the docs : signals and slots

    bq. Advanced Signals and Slots Usage:
    For cases where you may require information on the sender of the signal, Qt provides the QObject::sender() function, which returns a pointer to the object that sent the signal.

    in your case qsignalmapper could be an even better solution.

  • Thank you very much :)

    I'll try it tomorrow.

  • If you create a menu button, you don't use signal/slot with custom slots, you attach the menu direct to the push button. So QSignalMapper does not help here.

  • yes, you are right, i use the button's Hasfocus method to indicate it. it's ugly but it works.
    many thanks:)

  • The hasFocus() method doesn't work for me either. Anyone have any more suggestions? Since the QPushButton::setMenu() function exists, someone must know how to use it contextually..

  • If you reuse a QMenu for two buttons, it's supposed to be the same. If this is not true, use two different menus, probably sharing the same actions.

  • I'm not sure I totally agree with that statement. I think it makes sense to want to attach a context to a menu (-action). Considder a context menu for a list of items. The menu contains a set of actions that can operate on the items. I think it makes sense to

    reuse the same menu and the same actions as implementation for the operations, and

    wish to know at the action level what the context of the operation is.

    This case is not that different.

    I can see a case for having some kind of context for actions, but no ready-made solution for it.

  • Two pushbuttons are static. I just would go the easy way and create two menus. And we're not talking about context menus (these are easy to manipulate via the Qt::ContextMenuPolicy and the customContextMenuRequested signal), but a "regular" button menu.

    One could try to subclass QPushButton and override slot showMenu. Albeit that one is not virtual by design, all slots are inherently virtual when called via the metacall/signal-slot mechanism. I would not bet that this works out in all cases, though.

  • The problem is, when triggered() is called by a particular menu, whether the same menu is used in two buttons or you have different menus, you cannot work out which QPushButton the triggering menu is attached to.

    I tried looking at the parent() of the menus, but they are NULL. If I set the parent of them upon creation, then the menus are displayed when the buttons are drawn instead of when clicked.

    Even doing a pointer comparison between the event's sending QMenu and each QPushButton::menu() don't match.

  • Maybe you should describe exactly what you want to achieve - not the implementation approach, but what your UI should look and behave like. Maybe we can come up with a less problematic solution.

  • Sure.

    I've got a bunch of buttons that, when clicked, display the same menu:
    "Copy URL"

    When the event occurs, the menu enacts one of those methods, contextual to the button it's dropping down from.

  • The number of buttons is fixed?

  • At the moment.

  • So, when an action of the menu fires, the connected slot should use the URL associated with that button, right?

    If you still do not want to use separate menus and actions - which I think is the easiest and less problematic approach - you might want to connect to the pressed() signal of the buttons (use a [[Doc::QSignalMapper]] to associate an id or the like). I don't know if that works reliably in all and every corner cases (activation with the keyboard instead of the mouse comes into mind).

  • Thanks for all your help. I've resorted to hiding the URL text within the menu object using QObject::setProperty() and pulling it out again in the event. A bit of a fudge, but works.

  • You could considder an alternative approach:
    How about you subclass QPushButton. In this custom class, you can attach the menu already. Then, you give your button a set of signals corresponding with the items in the menu. You can give these signals an identifier argument to identify the instance of the button.

    That way, you will have no need to fiddle with sender() or with QSignalMapper.

Log in to reply