Multiple QAction and using sender() to get which got selected?
-
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) } }@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.@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(); }); -
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(); });@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);@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. -
@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; } -
A Anonymous_Banned275 referenced this topic on