Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Multiple QAction and using sender() to get which got selected?
Forum Updated to NodeBB v4.3 + New Features

Multiple QAction and using sender() to get which got selected?

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 6 Posters 2.4k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Calicoder
    wrote on last edited by
    #1

    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)
    	}
    }
    
    jsulmJ 1 Reply Last reply
    0
    • C Calicoder

      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)
      	}
      }
      
      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by jsulm
      #2

      @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.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply
      3
      • jsulmJ jsulm

        @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.

        C Offline
        C Offline
        Calicoder
        wrote on last edited by
        #3

        @jsulm Perfect, I'll try that. Thank you! Last question: so I have to pass the action as a parameter to the getAction() method? Is there a way to avoid that, just curious?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          When using a lambda like you do, yes you have to.
          Otherwise connect triggered directly to the slot and use sender.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          C 1 Reply Last reply
          2
          • SGaistS SGaist

            Hi,

            When using a lambda like you do, yes you have to.
            Otherwise connect triggered directly to the slot and use sender.

            C Offline
            C Offline
            Calicoder
            wrote on last edited by
            #5

            @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(); });
            
            JonBJ 1 Reply Last reply
            0
            • JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by JoeCFD
              #6

              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);

              JonBJ 1 Reply Last reply
              1
              • C Calicoder

                @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(); });
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @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) match QAction::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 use sender(), which has some issues; after C++ lambdas and connect() support for new-style syntax, if you want the signaller/sender do the lambda with the explicit parameter, that's just how it is.

                1 Reply Last reply
                1
                • JoeCFDJ JoeCFD

                  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);

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @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.

                  1 Reply Last reply
                  1
                  • M Offline
                    M Offline
                    mpergand
                    wrote on last edited by mpergand
                    #9

                    @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;
                    }
                    
                    1 Reply Last reply
                    1
                    • C Offline
                      C Offline
                      Calicoder
                      wrote on last edited by
                      #10

                      Appreciate the help, I'll take all your suggestions and learn from them. Thank you!

                      1 Reply Last reply
                      0
                      • A Anonymous_Banned275 referenced this topic on

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved