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. Connect signals with arguments
Forum Updated to NodeBB v4.3 + New Features

Connect signals with arguments

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 7 Posters 16.6k Views 6 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.
  • L Offline
    L Offline
    Lc44bzh
    wrote on last edited by
    #1

    Hello,
    I am trying to do a small videogame with QT for school.
    The main goal is to fight ennemies and go the further.
    When you defite a enemy, you can get item carried by him, and that is my point.
    To get the item, I press a button which is connected to a function that add item to hero's backpack.
    I have to give the item in argument, that why I defined a special class for my button, ItemButton, which extends QPushButton.
    Here is itembutton.cpp

    void ItemButton::emitclicked(Item new_item){
    
        emit clicked();
    
    }
    

    and itembutton.h

    #ifndef ITEMBUTTON_H
    #define ITEMBUTTON_H
    #include <QPushButton>
    #include "item.h"
    
    class ItemButton : public QPushButton
    {
    
    public:
    signals:
        void emitclicked(Item new_item);
    
    };
    #endif // ITEMBUTTON_H
    

    When i connect my button to this function by

    connect(button, SIGNAL(emitclicked(actual_ennemy->getItems().getItem(i))), this, SLOT(new_item(actual_ennemy->getItems().getItem(i))));
    

    i get the following error :

    QObject::connect: No such signal QPushButton::emitclicked(actual_ennemy->getItems().getItem(i)) in ..\Programmation\mainwindow.cpp:501
    

    So QT think i call a signal from QPushButton. But button is a ItemButton (ItemButton *button;)
    So, how can i connect to my signal defined in ItemButton ? Thanks

    jsulmJ 1 Reply Last reply
    0
    • L Lc44bzh

      Hello,
      I am trying to do a small videogame with QT for school.
      The main goal is to fight ennemies and go the further.
      When you defite a enemy, you can get item carried by him, and that is my point.
      To get the item, I press a button which is connected to a function that add item to hero's backpack.
      I have to give the item in argument, that why I defined a special class for my button, ItemButton, which extends QPushButton.
      Here is itembutton.cpp

      void ItemButton::emitclicked(Item new_item){
      
          emit clicked();
      
      }
      

      and itembutton.h

      #ifndef ITEMBUTTON_H
      #define ITEMBUTTON_H
      #include <QPushButton>
      #include "item.h"
      
      class ItemButton : public QPushButton
      {
      
      public:
      signals:
          void emitclicked(Item new_item);
      
      };
      #endif // ITEMBUTTON_H
      

      When i connect my button to this function by

      connect(button, SIGNAL(emitclicked(actual_ennemy->getItems().getItem(i))), this, SLOT(new_item(actual_ennemy->getItems().getItem(i))));
      

      i get the following error :

      QObject::connect: No such signal QPushButton::emitclicked(actual_ennemy->getItems().getItem(i)) in ..\Programmation\mainwindow.cpp:501
      

      So QT think i call a signal from QPushButton. But button is a ItemButton (ItemButton *button;)
      So, how can i connect to my signal defined in ItemButton ? Thanks

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Lc44bzh said in Connect signals with arguments:

      emitclicked(actual_ennemy->getItems().getItem(i))

      You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
      Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

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

      L 1 Reply Last reply
      5
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #3

        There are several issues with your code:

        • signal cannot have implementation (you can't have emitclicked() body in cpp file, only declaration in header)
        • connect statement only connects signals and slot, you cannot provide any actual data there like actual_ennemy->getItems().getItem(i)). The only stuff you should provide there are argument types. Even better: use new functor-based connection syntax https://doc.qt.io/qt-5/signalsandslots-syntaxes.html
        • connect is called only once, when a connection is made - so it has no idea what data will be sent through it later

        So QT think i call a signal from QPushButton

        Not quite, your code is simply wrong. Here is how to fix it:

        • connect your button's clicked() signal (it can be a normal QPushButton, no need for a subclass!) to a slot in your controller class (seems like you're using MainWindow for that), like this:
          connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked
        • in your slot, get the necessary data:
        MainWindow::onButtonClicked()
        {
          actual_ennemy->getItems().getItem(i);
        }
        
        • of course, you also need to know which i to use, and actual_ennemy needs to be set. I know too little of your program to tell you how to do that

        (Z(:^

        1 Reply Last reply
        6
        • jsulmJ jsulm

          @Lc44bzh said in Connect signals with arguments:

          emitclicked(actual_ennemy->getItems().getItem(i))

          You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
          Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

          L Offline
          L Offline
          Lc44bzh
          wrote on last edited by
          #4

          @jsulm said in Connect signals with arguments:

          @Lc44bzh said in Connect signals with arguments:

          emitclicked(actual_ennemy->getItems().getItem(i))

          You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
          Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

          I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

          @sierdzio said in Connect signals with arguments:

          There are several issues with your code:

          • signal cannot have implementation (you can't have emitclicked() body in cpp file, only declaration in header)
          • connect statement only connects signals and slot, you cannot provide any actual data there like actual_ennemy->getItems().getItem(i)). The only stuff you should provide there are argument types. Even better: use new functor-based connection syntax https://doc.qt.io/qt-5/signalsandslots-syntaxes.html
          • connect is called only once, when a connection is made - so it has no idea what data will be sent through it later

          So QT think i call a signal from QPushButton

          Not quite, your code is simply wrong. Here is how to fix it:

          • connect your button's clicked() signal (it can be a normal QPushButton, no need for a subclass!) to a slot in your controller class (seems like you're using MainWindow for that), like this:
            connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked
          • in your slot, get the necessary data:
          MainWindow::onButtonClicked()
          {
            actual_ennemy->getItems().getItem(i);
          }
          
          • of course, you also need to know which i to use, and actual_ennemy needs to be set. I know too little of your program to tell you how to do that

          Thank you, I used your solution and it's working. I defined the objectname of each button with i, and when I am in onButtonClicked, I just read the sender object name to get the index of my item.

          Thank for your help both of you.

          Pl45m4P SGaistS S 3 Replies Last reply
          1
          • L Lc44bzh

            @jsulm said in Connect signals with arguments:

            @Lc44bzh said in Connect signals with arguments:

            emitclicked(actual_ennemy->getItems().getItem(i))

            You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
            Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

            I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

            @sierdzio said in Connect signals with arguments:

            There are several issues with your code:

            • signal cannot have implementation (you can't have emitclicked() body in cpp file, only declaration in header)
            • connect statement only connects signals and slot, you cannot provide any actual data there like actual_ennemy->getItems().getItem(i)). The only stuff you should provide there are argument types. Even better: use new functor-based connection syntax https://doc.qt.io/qt-5/signalsandslots-syntaxes.html
            • connect is called only once, when a connection is made - so it has no idea what data will be sent through it later

            So QT think i call a signal from QPushButton

            Not quite, your code is simply wrong. Here is how to fix it:

            • connect your button's clicked() signal (it can be a normal QPushButton, no need for a subclass!) to a slot in your controller class (seems like you're using MainWindow for that), like this:
              connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked
            • in your slot, get the necessary data:
            MainWindow::onButtonClicked()
            {
              actual_ennemy->getItems().getItem(i);
            }
            
            • of course, you also need to know which i to use, and actual_ennemy needs to be set. I know too little of your program to tell you how to do that

            Thank you, I used your solution and it's working. I defined the objectname of each button with i, and when I am in onButtonClicked, I just read the sender object name to get the index of my item.

            Thank for your help both of you.

            Pl45m4P Offline
            Pl45m4P Offline
            Pl45m4
            wrote on last edited by Pl45m4
            #5

            @Lc44bzh said in Connect signals with arguments:

            I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

            The tutorial itself is not wrong. Maybe you misunderstood it :)

            I defined the objectname of each button with i, and when I am in onButtonClicked, I just read the sender object name to get the index of my item

            Using objectNames is possible, but not the best solution, since you heavily rely on them then.
            (Edit: actually, using objectNames to get your indices is bad style and very ugly)

            Edit:

            Depends on your use case and how the rest of your game should work, but consider using something like a QMap or any other container to store your items and/or map them to your buttons / enemies, or whatever you want to do with them.

            • https://doc.qt.io/qt-5/qmap.html#details

            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            1 Reply Last reply
            1
            • L Lc44bzh

              @jsulm said in Connect signals with arguments:

              @Lc44bzh said in Connect signals with arguments:

              emitclicked(actual_ennemy->getItems().getItem(i))

              You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
              Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

              I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

              @sierdzio said in Connect signals with arguments:

              There are several issues with your code:

              • signal cannot have implementation (you can't have emitclicked() body in cpp file, only declaration in header)
              • connect statement only connects signals and slot, you cannot provide any actual data there like actual_ennemy->getItems().getItem(i)). The only stuff you should provide there are argument types. Even better: use new functor-based connection syntax https://doc.qt.io/qt-5/signalsandslots-syntaxes.html
              • connect is called only once, when a connection is made - so it has no idea what data will be sent through it later

              So QT think i call a signal from QPushButton

              Not quite, your code is simply wrong. Here is how to fix it:

              • connect your button's clicked() signal (it can be a normal QPushButton, no need for a subclass!) to a slot in your controller class (seems like you're using MainWindow for that), like this:
                connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked
              • in your slot, get the necessary data:
              MainWindow::onButtonClicked()
              {
                actual_ennemy->getItems().getItem(i);
              }
              
              • of course, you also need to know which i to use, and actual_ennemy needs to be set. I know too little of your program to tell you how to do that

              Thank you, I used your solution and it's working. I defined the objectname of each button with i, and when I am in onButtonClicked, I just read the sender object name to get the index of my item.

              Thank for your help both of you.

              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @Lc44bzh hi and welcome to devnet,

              You misunderstood the tutorial. You are mixing the function signature with function parameters.

              The connect statement in its old form takes string parameters that are the signature of the signal function and the signature of the slot function. You can't pass parameter values in there (nor can you with the syntax).

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

              1 Reply Last reply
              1
              • L Lc44bzh

                @jsulm said in Connect signals with arguments:

                @Lc44bzh said in Connect signals with arguments:

                emitclicked(actual_ennemy->getItems().getItem(i))

                You can't pass parameters to signal when you connect. Parameters are passed to the signal when the signal is emitted. Same applies to slots: those get their parameters from the signal.
                Please read https://doc.qt.io/qt-5/signalsandslots.html There are also examples.

                I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

                @sierdzio said in Connect signals with arguments:

                There are several issues with your code:

                • signal cannot have implementation (you can't have emitclicked() body in cpp file, only declaration in header)
                • connect statement only connects signals and slot, you cannot provide any actual data there like actual_ennemy->getItems().getItem(i)). The only stuff you should provide there are argument types. Even better: use new functor-based connection syntax https://doc.qt.io/qt-5/signalsandslots-syntaxes.html
                • connect is called only once, when a connection is made - so it has no idea what data will be sent through it later

                So QT think i call a signal from QPushButton

                Not quite, your code is simply wrong. Here is how to fix it:

                • connect your button's clicked() signal (it can be a normal QPushButton, no need for a subclass!) to a slot in your controller class (seems like you're using MainWindow for that), like this:
                  connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked
                • in your slot, get the necessary data:
                MainWindow::onButtonClicked()
                {
                  actual_ennemy->getItems().getItem(i);
                }
                
                • of course, you also need to know which i to use, and actual_ennemy needs to be set. I know too little of your program to tell you how to do that

                Thank you, I used your solution and it's working. I defined the objectname of each button with i, and when I am in onButtonClicked, I just read the sender object name to get the index of my item.

                Thank for your help both of you.

                S Offline
                S Offline
                SimonSchroeder
                wrote on last edited by
                #7

                @Lc44bzh said in Connect signals with arguments:

                I saw on https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1899731-utilisez-les-signaux-et-les-slots that it may be possible. Never mind.

                In the connect statement you only have the types of the parameters. However, you cannot provide the actual parameters in the connect statement. Instead you have to provide them when you call (emit) the signal. A button has no parameters when clicked. You can connect clicked() to some slot which extracts the information and then emit another signal with this parameter connected to the slot you already initially had.

                There might be a shortcut for what you want to do. All this assumes that you already know actual_ennemy and the index i when you create the button (which I assume is the case). Then you can replace your connect with the following:

                connect(button, &QPushButton::clicked, this, [this](){ new_item(actual_ennemy->getItems().getItem(i)); });
                

                This is the newer connect syntax. Your button can now be a QPushButton again. The third parameter to connect is just a context object. this makes sense in this context. Instead of an actual slot here we connect to a lambda function. Depending on which variables are member of your class and which are local variables you might have to capture additional variables in the lambda. This is the easiest way I know to quickly connect a signal with fewer arguments than the required slot.

                1 Reply Last reply
                0
                • L Offline
                  L Offline
                  Lc44bzh
                  wrote on last edited by
                  #8

                  Thanks for your answers. Now, when I create a button, I store the item pointer associated with him. And I use connect with Item type, so I can get the item related to my button. Here is my code, and it work properly :
                  itembutton.h :

                  #ifndef ITEMBUTTON_H
                  #define ITEMBUTTON_H
                  #include <QPushButton>
                  
                  #include "item.h"
                  #include <iostream>
                  using namespace std;
                  
                  class ItemButton : public QPushButton
                  {
                      Q_OBJECT
                      
                  public:
                      ItemButton(Item * it, QWidget * parent);
                      
                  Q_SIGNAL void clicked(Item *);
                  
                  private:
                  Q_SLOT void reemitClicked();
                      
                  private:
                      Item *myitem;
                  };
                  #endif // ITEMBUTTON_H
                  
                  

                  itembutton.cpp :

                  #include "itembutton.h"
                  
                  ItemButton::ItemButton(Item *it, QWidget *parent) : QPushButton(parent)
                  {
                      myitem = it;
                      connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
                  }
                  
                  
                  void ItemButton::reemitClicked()
                  {
                      emit clicked(myitem);
                  }
                  
                  

                  connect function in mainwindow.cpp :

                  connect(button, SIGNAL(clicked(Item*)), this, SLOT(new_item(Item*)));
                  
                  S JonBJ 2 Replies Last reply
                  2
                  • L Lc44bzh

                    Thanks for your answers. Now, when I create a button, I store the item pointer associated with him. And I use connect with Item type, so I can get the item related to my button. Here is my code, and it work properly :
                    itembutton.h :

                    #ifndef ITEMBUTTON_H
                    #define ITEMBUTTON_H
                    #include <QPushButton>
                    
                    #include "item.h"
                    #include <iostream>
                    using namespace std;
                    
                    class ItemButton : public QPushButton
                    {
                        Q_OBJECT
                        
                    public:
                        ItemButton(Item * it, QWidget * parent);
                        
                    Q_SIGNAL void clicked(Item *);
                    
                    private:
                    Q_SLOT void reemitClicked();
                        
                    private:
                        Item *myitem;
                    };
                    #endif // ITEMBUTTON_H
                    
                    

                    itembutton.cpp :

                    #include "itembutton.h"
                    
                    ItemButton::ItemButton(Item *it, QWidget *parent) : QPushButton(parent)
                    {
                        myitem = it;
                        connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
                    }
                    
                    
                    void ItemButton::reemitClicked()
                    {
                        emit clicked(myitem);
                    }
                    
                    

                    connect function in mainwindow.cpp :

                    connect(button, SIGNAL(clicked(Item*)), this, SLOT(new_item(Item*)));
                    
                    S Offline
                    S Offline
                    SimonSchroeder
                    wrote on last edited by
                    #9

                    @Lc44bzh said in Connect signals with arguments:

                    Now, when I create a button, I store the item pointer associated with him. And I use connect with Item type, so I can get the item related to my button.

                    Well done. This is also a proper solution. It seems that you significantly improved your understanding of Qt's signals and slots.

                    1 Reply Last reply
                    1
                    • L Lc44bzh

                      Thanks for your answers. Now, when I create a button, I store the item pointer associated with him. And I use connect with Item type, so I can get the item related to my button. Here is my code, and it work properly :
                      itembutton.h :

                      #ifndef ITEMBUTTON_H
                      #define ITEMBUTTON_H
                      #include <QPushButton>
                      
                      #include "item.h"
                      #include <iostream>
                      using namespace std;
                      
                      class ItemButton : public QPushButton
                      {
                          Q_OBJECT
                          
                      public:
                          ItemButton(Item * it, QWidget * parent);
                          
                      Q_SIGNAL void clicked(Item *);
                      
                      private:
                      Q_SLOT void reemitClicked();
                          
                      private:
                          Item *myitem;
                      };
                      #endif // ITEMBUTTON_H
                      
                      

                      itembutton.cpp :

                      #include "itembutton.h"
                      
                      ItemButton::ItemButton(Item *it, QWidget *parent) : QPushButton(parent)
                      {
                          myitem = it;
                          connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
                      }
                      
                      
                      void ItemButton::reemitClicked()
                      {
                          emit clicked(myitem);
                      }
                      
                      

                      connect function in mainwindow.cpp :

                      connect(button, SIGNAL(clicked(Item*)), this, SLOT(new_item(Item*)));
                      
                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @Lc44bzh
                      Indeed well done!

                      As it's my bug-bear, can I suggest you go further and change over from using SIGNAL/SLOT() macros to the New Signal Slot Syntax? You really will benefit, with compile-time checking of your signals, slots & parameters. Note how @SimonSchroeder used this in his example (it used a lambda for the slot, which is more complicated but very powerful, but nonetheless used the new style syntax, as one has to anyway for lambdas).

                      For example,

                      connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
                      

                      would be better written as

                      connect(this, &ItemButton::clicked, this, &ItemButton::reemitClicked);
                      
                      1 Reply Last reply
                      5

                      • Login

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