Pass multiple arguments to slot

12.3k views Asked by At

I'm currently working on a game with a friend of mine, and now we are kind of stuck. We need to pass two arguments to a slot. I want to use one slot for two buttons, and one of the buttons will be used for adding, and the other one for subtracting. This will be one of the arguments, either 0 (for subtracting) or 1 (for adding). The other argument will be a kind of ID, because i will have several sets of these two buttons. I've used several other slots in my code, and on these slots I've been using QSignalMapper like this:

Button * button = new Button(argument1, argument2, argument3);

int num = 1;

QSignalMapper * signalMapper = new QSignalMapper(this);

connect(button, SIGNAL(clicked()), signalMapper, SLOT(map)));
signalMapper->setMapping(button, num);
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(mySlot(int)));

scene->addItem(button);

Is there any way I can pass two arguments to a slot?

3

There are 3 answers

1
Alexander Saprykin On

QSignalMapper has a single parameter only. But you can use one of the following ways to split buttons into the several sets:

  • start each set ID from a known number, i.e. first set starts from 100, the second set from 200 and so on, and you can easily detect the set dividing a number by 100: 102 stands for the first set and button ID = 2;
  • use mapping with QString where you can use some token to split a set number from a button number, i.e. 1;2 (the first set, button ID = 2) using QString::split().

Example of the slot:

void mySLot (const QString& id)
{
    QStringList tokens = id.split (";");

    if (tokens.count () == 2) {
        int setId    = tokens.at(0).toInt ();
        int buttonId = tokens.at(1).toInt ();

        /* Your code goes here */
    }
}
6
jonspaceharper On

Use the sender() function instead:

void mySlot()
{
    if (sender() == addButton)
        ...
    else
        ...
}

In your case, you can remove the int argument from mySlot and do the following:

 connect(addButton, SIGNAL(clicked()), someObject, SLOT(mySlot()));
 connect(subButton, SIGNAL(clicked()), someObject, SLOT(mySlot()));

Then use the sender function to determine the source.

To directly answer your question, yes, you can define a slot that accepts up to 8 arguments (pre C++11) or any number (C++11 or later). The issue is that they must be connected to a signal with as many or more parameters.

Example, if you have a signal with the signature notify(int, bool, QString) you can connect it to a slot with any of the following signatures:

  • someSlot(int)
  • someSlot(int, bool)
  • someSlot(int, bool, QString)
6
JvO On

[completely revised answer]

So, we have an Button object with multiple arguments that need to be passed on in a slot.

class Button
{
   Q_OBJECT
 public:
   int m_arg1, m_arg2, m_arg3;

   Button(int arg1, int arg2, int arg3)
   {
      m_arg1 = arg1;
      m_arg2 = arg2;
      m_arg3 = arg3;
   };

   /// some function that emits a click signal with 2 of my arguments
   void doSomething()
   {
       emit clicked (m_arg2, m_arg3);
   }

 signals:
   void clicked(int, int);
};

Then, later on:

Button *button = new Button(val1, val2, val3);
connect(button, SIGNAL(clicked(int, int)), this, SLOT(mySlot(int, int)));

MyReceiver::mySlot(int a1, int a2)
{
  // see who called me, then use arguments
  if (addButton == sender())
  {
     x = a1 + a2;
  }
  else if (subButton == sender())
  {
     x= a1 - a2;
  }
}