2

below I quoted my code. The problem is easy to describe. selectedItem->text is not the right way to differ what action was selected in the menu. How to do it right?

void RView::ShowContextMenu(const QPoint& pos) // this is a slot
{
// for most widgets
QPoint globalPos = statusWidget->mapToGlobal(pos);
// for QAbstractScrollArea and derived classes you would use:
// QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

QMenu myMenu;
myMenu.addAction("first");
myMenu.addAction("second");

QAction* selectedItem = myMenu.exec(globalPos);
if (selectedItem)
{ 
    if(selectedItem->text == "first")
     // do something 
    if(selectedItem->text == "second")
     // do other stuff
}
else
{
    // nothing was chosen
}
}
drescherjm
  • 10,365
  • 5
  • 44
  • 64
tux007
  • 282
  • 1
  • 3
  • 17
  • ***How to do it right?*** Most likely to use signals and slots. Connect your QAction triggered signal(s) to slots in your RView class. – drescherjm Nov 26 '16 at 18:31

1 Answers1

2

You should rather compare the QActions directly and either use the comparison of selectedItem as you do in your ifs or better yet connect each action to the desired slot (or lambda if they are one time things localised to this context).

QMenu myMenu;
QAction *action1 = myMenu.addAction("first");
QAction *action2 = myMenu.addAction("second");
connect(action1, &QAction::triggered, [](){/*lambda code here*/});
connect(action2, &QAction::triggered, [](){/*lambda code here*/});
myMenu.exec(statusWidget->mapToGlobal(pos));

EDIT: For Qt4 you would use slots and old connect syntax:

QMenu myMenu;
QAction *action1 = myMenu.addAction("first");
QAction *action2 = myMenu.addAction("second");
connect(action1, SIGNAL(triggered()), this, SLOT(doStuff()));
connect(action2, SIGNAL(triggered()), this, SLOT(doOtherStuff()));
myMenu.exec(statusWidget->mapToGlobal(pos));

For this to work you will need "doStuff" and "doOtherStuff" to be declared as slots in your header taking no arguments (becuase the signal QAction::triggered() have none). The code you want done will go to definitions of these slots:

class RView
{
public slots:
    void doStuff() { /*do stuff*/ }
    void doOtherStuff() { /*do other stuff*/ }
};
Resurrection
  • 3,916
  • 2
  • 34
  • 56
  • the compiler don't know triggered – tux007 Nov 26 '16 at 18:46
  • Sorry, should have been QAction, not QObject. Corrected it. And the lambda code is whatever you need done when that action is triggered. The "//do something" and "//do other stuff" in OP. – Resurrection Nov 26 '16 at 18:59
  • Whatever you want executed when the action is triggered. To use a lambda for this assumes you are using some version of Qt5. – drescherjm Nov 26 '16 at 18:59
  • that's not good, now I have problems, because it is in lambda code. – tux007 Nov 26 '16 at 19:08
  • and triggered is still unknown. – tux007 Nov 26 '16 at 19:15
  • 1
    ***and triggered is still unknown.*** Do you need to know that? I mean you should have 1 action per menu item. Each action has its own lambda to execute code for that action. – drescherjm Nov 26 '16 at 19:36
  • okay, ist not triggered what is unkown... there is no function named connect with this arguments and triggerd is the problem. – tux007 Nov 26 '16 at 19:39
  • 1
    Are you using Qt5? Maybe you need to include If you are using Qt4 lambdas will not work. – drescherjm Nov 26 '16 at 19:41
  • I'm using QT4, and I can't change. But I guess there must be another way, to differ what has been clicked. – tux007 Nov 26 '16 at 20:14
  • ***But I guess there must be another way, to differ what has been clicked.*** Yes, there is a different connect syntax and you can't use the lambda but you can use a slots in your RView class. – drescherjm Nov 26 '16 at 20:23
  • drescherjm, can you please write an example? – tux007 Nov 26 '16 at 20:34
  • Maybe later this evening. I have company and I am going out soon. – drescherjm Nov 26 '16 at 20:45
  • @Michael Vlach, thank you!! but there is a copy paste error. Both connect functions react on action1 ;) – tux007 Nov 27 '16 at 08:59
  • @tux007 Right :-) Fixed that and glad to be of service. – Resurrection Nov 27 '16 at 11:29
  • If you have fixed actions, use one slot for each. If the number of actions is dependent on a runtime value, use a `QSignalMapper` or store the reference value as `QAction::data()` and retrieve it in the slot – Kevin Krammer Nov 27 '16 at 13:36
  • @Kevin Krammer, I hate to resurrect an old thread, but how do I retrieve the QAction's data in the slot? – AlastairG Aug 27 '21 at 14:13
  • Never mind: `QAction *action = qobject_cast(QObject::sender());` – AlastairG Aug 27 '21 at 14:19