Multiple QAction and using sender() to get which got selected?
-
wrote on 4 Nov 2021, 15:14 last edited by
Howdy fellow QT'ers, hope your days are going well so far. Wonder if you experts know why I'm getting these results? I've been reading the QT docs for the past 3 days and not getting anywhere with my test app. I noticed that QT has the QMenu class to create menus and that's so cool. Is there a way to use QObject::sender() to get what menu selection was selected as it uses a set of QActions? I'm using Action01 and Action02 as my 2 menu choices, can getAction() get that info without literally using a parameter to set it and send it to other methods? I also see that the action variable gets a QAction returned with all sorts of info set in it, how can I pull that data out?
Thanks again and to many successful compiles!
void App::menu() { QMenu actionMenu("ActionMenu", this); QAction action01("Action01", this); QAction action02("Action02", this); connect(&action01, &QAction::triggered, this, [=]() {getAction(); }); connect(&action02, &QAction::triggered, this, [=]() {getAction(); }); actionMenu.addAction(&action01); actionMenu.addAction(&action02); actionMenu.exec(QCursor::pos()); } void App::getAction() { if (sender() != nullptr) { QAction* newAction = new QAction(sender()); QAction* action = qobject_cast<QAction*>(sender()); qDebug() << sender(); // returns QAction(0x47bcf699c0) qDebug() << newAction; // returns QAction(0x1db458dd800 text="" menuRole=TextHeuristicRole visible=true) qDebug() << action; // returns QAction(0x47bcf699c0 text="Action01" toolTip="Action01" menuRole=TextHeuristicRole visible=true) or QAction(0x47bcf699c0 text="Action02" toolTip="Action02" menuRole=TextHeuristicRole visible=true) qDebug() << action->data(); // returns QVariant(Invalid) } }
-
Howdy fellow QT'ers, hope your days are going well so far. Wonder if you experts know why I'm getting these results? I've been reading the QT docs for the past 3 days and not getting anywhere with my test app. I noticed that QT has the QMenu class to create menus and that's so cool. Is there a way to use QObject::sender() to get what menu selection was selected as it uses a set of QActions? I'm using Action01 and Action02 as my 2 menu choices, can getAction() get that info without literally using a parameter to set it and send it to other methods? I also see that the action variable gets a QAction returned with all sorts of info set in it, how can I pull that data out?
Thanks again and to many successful compiles!
void App::menu() { QMenu actionMenu("ActionMenu", this); QAction action01("Action01", this); QAction action02("Action02", this); connect(&action01, &QAction::triggered, this, [=]() {getAction(); }); connect(&action02, &QAction::triggered, this, [=]() {getAction(); }); actionMenu.addAction(&action01); actionMenu.addAction(&action02); actionMenu.exec(QCursor::pos()); } void App::getAction() { if (sender() != nullptr) { QAction* newAction = new QAction(sender()); QAction* action = qobject_cast<QAction*>(sender()); qDebug() << sender(); // returns QAction(0x47bcf699c0) qDebug() << newAction; // returns QAction(0x1db458dd800 text="" menuRole=TextHeuristicRole visible=true) qDebug() << action; // returns QAction(0x47bcf699c0 text="Action01" toolTip="Action01" menuRole=TextHeuristicRole visible=true) or QAction(0x47bcf699c0 text="Action02" toolTip="Action02" menuRole=TextHeuristicRole visible=true) qDebug() << action->data(); // returns QVariant(Invalid) } }
Lifetime Qt Championwrote on 4 Nov 2021, 15:24 last edited by jsulm 11 Apr 2021, 15:24@Calicoder said in Multiple QAction and using sender() to get which got selected?:
connect(&action01, &QAction::triggered, this, = {getAction(); });
connect(&action02, &QAction::triggered, this, = {getAction(); });connect(&action01, &QAction::triggered, this, [&action01,=]() {getAction(action01); }); connect(&action02, &QAction::triggered, this, [&action02,=]() {getAction(action02); });
Also, adjust the void App::getAction() signature accordingly.
-
@Calicoder said in Multiple QAction and using sender() to get which got selected?:
connect(&action01, &QAction::triggered, this, = {getAction(); });
connect(&action02, &QAction::triggered, this, = {getAction(); });connect(&action01, &QAction::triggered, this, [&action01,=]() {getAction(action01); }); connect(&action02, &QAction::triggered, this, [&action02,=]() {getAction(action02); });
Also, adjust the void App::getAction() signature accordingly.
-
Hi,
When using a lambda like you do, yes you have to.
Otherwise connect triggered directly to the slot and use sender. -
Hi,
When using a lambda like you do, yes you have to.
Otherwise connect triggered directly to the slot and use sender.wrote on 4 Nov 2021, 15:46 last edited by@SGaist Ok I'm starting to see the bigger picture here, thanks. I always figured this type of connection does connect triggered directly to the slot?
connect(&action01, &QAction::triggered, this, [=]() {getAction(); }); connect(&action02, &QAction::triggered, this, [=]() {getAction(); });
-
wrote on 4 Nov 2021, 15:48 last edited by JoeCFD 11 Apr 2021, 15:53
SGaist is right. In this case, lamba is not needed. Simply use slot onActionClicked and
connect(&action01, &QAction::triggered, this, &App::onActionClicked);
connect(&action02, &QAction::triggered, this, &App::onActionClicked);make action01 and action02 global.
Inside onActionClicked simply compare
if (sender() ==action01 )
else if (sender() ==action02 )The following variables are not pointers?
QMenu actionMenu("ActionMenu", this);
QAction action01("Action01", this);
QAction action02("Action02", this);The right way to create them is
auto actionMenu = new QMenu ("ActionMenu", this);
auto action01 = new QAction ("Action01", this);
auto action02 = new QAction ("Action02", this); -
@SGaist Ok I'm starting to see the bigger picture here, thanks. I always figured this type of connection does connect triggered directly to the slot?
connect(&action01, &QAction::triggered, this, [=]() {getAction(); }); connect(&action02, &QAction::triggered, this, [=]() {getAction(); });
wrote on 4 Nov 2021, 15:51 last edited by JonB 11 Apr 2021, 15:52@Calicoder said in Multiple QAction and using sender() to get which got selected?:
directly to the slot
Would mean with no lambda, just method:
connect(&action01, &QAction::triggered, this, &ThisClass::getAction });
So no chance to pass your own parameters, and
ThisClass::getAction()
's signature must (more or less, it can have less parameters but not more) matchQAction::triggered
's signature.so I have to pass the action as a parameter to the getAction() method? Is there a way to avoid that, just curious?
What you would like is that all
connect()
s automatically pass the signalling object as the first parameter to any slot. But Qt takes a "minimal" approach, and just does not bother to do that. Often you don't need to know the signaller. When you do, in the old days you had to usesender()
, which has some issues; after C++ lambdas andconnect()
support for new-style syntax, if you want the signaller/sender do the lambda with the explicit parameter, that's just how it is. -
SGaist is right. In this case, lamba is not needed. Simply use slot onActionClicked and
connect(&action01, &QAction::triggered, this, &App::onActionClicked);
connect(&action02, &QAction::triggered, this, &App::onActionClicked);make action01 and action02 global.
Inside onActionClicked simply compare
if (sender() ==action01 )
else if (sender() ==action02 )The following variables are not pointers?
QMenu actionMenu("ActionMenu", this);
QAction action01("Action01", this);
QAction action02("Action02", this);The right way to create them is
auto actionMenu = new QMenu ("ActionMenu", this);
auto action01 = new QAction ("Action01", this);
auto action02 = new QAction ("Action02", this);wrote on 4 Nov 2021, 15:55 last edited by JonB 11 Apr 2021, 15:56@JoeCFD said in Multiple QAction and using sender() to get which got selected?:
make action01 and action02 global.
Inside onActionClicked simply compare
if (sender() ==action01 )
else if (sender() ==action02 )But why use
sender()
now that we have lambdas? This approach has problems when the coder does choose to use a lambda to connect a signal to the slot, for whatever reason. -
wrote on 4 Nov 2021, 16:13 last edited by mpergand 11 Apr 2021, 16:21
@Calicoder said in Multiple QAction and using sender() to get which got selected?:
qDebug() << action->data(); // returns QVariant(Invalid)
Suppose you want to call a method with the value (here an int) of the QVariant for each action, you can do:
void App::menu() { QMenu actionMenu("ActionMenu"); QAction* action=actionMenu.addAction("Action01"); action->setData(1); action=actionMenu.addAction("Action02"); action->setData(2); connect(&actionMenu, &QMenu::triggered, [this] (QAction* a) { qDebug()<<a; getAction(a->data().toInt()); }); actionMenu.exec(QCursor::pos()); } void App::getAction(const int p) { qDebug()<<p; }
-
wrote on 4 Nov 2021, 16:44 last edited by
Appreciate the help, I'll take all your suggestions and learn from them. Thank you!
-
1/10