2

I'm trying to connect a button to a function, so when I push the button, the function gets called with a specific parameter. I have

class FieldGridWidget : public QWidget
{
    Q_OBJECT

public:
    FieldGridWidget(QWidget *parent=0);
    ~FieldGridWidget();

public slots:
    void resizeGrid(int n);

private:
    QGridLayout* _gridLayout;
    QVector<QPushButton*> _buttonGrid;

};

then the button

_button3 = new QPushButton("3x3", this);

and I'm trying to connect it so if clicked, the resizeGrid function gets called with the parameter 3. For this, I'm trying

connect(_button3, SIGNAL(clicked()), _fieldGrid, SLOT(resizeGrid(3))); //this is line 21

but I get the runtime error QObject::connect: No such slot FieldGridWidget::resizeGrid(3) in ../filename.cpp:21

What am I doing wrong? Or how can I make it so if I press the button, resizeGrid(3) gets called? Thank you!

vsimkus
  • 335
  • 1
  • 10
lte__
  • 7,175
  • 25
  • 74
  • 131

3 Answers3

6

You cannot pass a value to a slot in Qt directly, as in SLOT(resizeGrid(3)). The argument to SLOT should be just the signature of your method (resizeGrid()).

There are two ways how to add an argument to a slot. This question about how to pass arguments to a slot shows some solutions, repeated here. (Go upvote them!)

The modern way : Qt5 and C++11

Instead of connecting a slot, connect to functor, as described by Kuba Ober in this answer:

connect(action1,  &QAction::triggered, this, [this]{ onStepIncreased(1); });
connect(action5,  &QAction::triggered, this, [this]{ onStepIncreased(5); });
connect(action10, &QAction::triggered, this, [this]{ onStepIncreased(10); });
connect(action25, &QAction::triggered, this, [this]{ onStepIncreased(25); });
connect(action50, &QAction::triggered, this, [this]{ onStepIncreased(50); });

Old fashioned : QSignalMapper

You can use a QSignalMapper to perform what you want, as described by TonyK in this answer:

QSignalMapper* signalMapper = new QSignalMapper (this) ;
connect (action1, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action5, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action10, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action25, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action50, SIGNAL(triggered()), signalMapper, SLOT(map())) ;

signalMapper -> setMapping (action1, 1) ;
signalMapper -> setMapping (action5, 5) ;
signalMapper -> setMapping (action10, 10) ;
signalMapper -> setMapping (action25, 25) ;
signalMapper -> setMapping (action50, 50) ;

connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(resizeGrid(int))) ;
Community
  • 1
  • 1
vsimkus
  • 335
  • 1
  • 10
3

Signatures of signals and slots must match - if not fully, then at least partially.

For example, you can connect a signal(int, float) to a slot(int), but you can't connect a signal(void) to a slot(int).

It is "sort of possible" to specify a slot parameter in the connection syntax, providing you are using Qt 5:

connect(_button3, &QPushButton::clicked, [=](){ _fieldGrid->resizeGrid(3); }); 

Of course, you could use the signal mapper in this particular case, but it is a rather clumsy solution - extra verbose and limited to only a single int, string, widget or QObject parameter. With lambdas those limitations do not apply.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • I'm trying this code: `connect(_button3, SIGNAL(clicked()), this, {_fieldGrid->resizeGrid(3) });` but now I get another error: `/filename.cpp:21: error: no matching function for call to 'MyMainClass::connect(QPushButton*&, const char*, MyMainClass* const, )' connect(_button3, SIGNAL(clicked()), this, { _fieldGrid->resizeGrid(3) });` Why is this? – lte__ Mar 06 '16 at 13:43
  • Because your code is wrong, I have given you the correct code. Who gave you that code? – dtech Mar 06 '16 at 14:24
  • No one, but your code also gives an error: `filename.cpp:21: error: no matching function for call to 'MyMainClass::connect(QPushButton*&, void (QAbstractButton::*)(bool), MyMainClass::MyMainClass(QWidget*)::__lambda0)' connect(_button3, &QPushButton::clicked, [=](){ _fieldGrid->resizeGrid(3); });` – lte__ Mar 06 '16 at 14:42
  • @lte__ - that code works. It requires at least Qt version 5 and a C++11 compiler. You also need a `CONFIG += c++11` in your PRO file to use C++11 features. What is your Qt version and compiler? – dtech Mar 06 '16 at 14:54
  • In the .pro file I see Desktop Qt 5.5.1 GCC 64bit, and I also have C++11. I cannot find the `CONFIG += c++11` in the pro file though. What do I do? – lte__ Mar 06 '16 at 15:11
  • Just copy/paste it in the PRO file. – dtech Mar 06 '16 at 15:15
1

clicked() and resizeGrid() signatures should be the same, so you can create function, for example, resizeGridForButton(), where resizeGrid(3) will be executed, or change resizeGrid() signature and transfer int n = 3 into it.

And it's not possible (example in the answer of vsimkus) to send params in connect(...). Also you can send them in emit part through signal params.

Here is a good article about slots and signals.

Anton
  • 127
  • 1
  • 3
  • 11