3

I'm designed a QTableWidget with QPushButton, I would like to connect these buttons with a slot to hide some rows.

I'm using a lambda expression to pass a number of a row. But the compiler doesn't recognized this expression :

connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this,i]{hideRows(i);});

I have this error:

error: no matching function for call to 'SoftwareUdpater::MainWidget::connect(QWidget*, void (QAbstractButton::*)(bool), SoftwareUdpater::MainWidget::displayTable()::<lambda(int)>)'
  • The function hideRows(int) is declared as a function. And, as a slot, it doesn't work,
  • CONFIG += c++11 is added in pro file,
  • My class MainWidget inherits from QWidget,
  • Q_OBJECT is added in the header.

So I don't udnerstand why connect() is not recognized by Qt 5.9.1 MinGw 32bit.

Edit: [this,i]() instead of [this](const int i) for the lambda expression

Liscare
  • 336
  • 2
  • 14
  • in addition to what the answer says, you most likely want to capture the `i` by value instead of taking it as a parameter `connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this,i](){hideRows(i);});` – PeterT Aug 04 '17 at 07:54
  • using both `[this,i]` and `(int i)` doesn't make much sense. Additionally it seems like you might need to downcast your QWidget* to QPushbutton* `connect((QPushButton*)this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this,i](){hideRows(i);});`. This is assuming that it always is a QPushbutton. – PeterT Aug 04 '17 at 08:54
  • That error message means, there is no such `connect` function, which takes those parameters. Most likely reason is, you are somehow not building with C++11, or you are somehow building with Qt4, or something else external like that. Perhaps you should edit the question to add complete error message, with list of what candidates were found. Also add the compile command used to build that file. – hyde Aug 04 '17 at 09:28
  • 1
    I'm a bit confused by the *::* part at the end of the error message. That seems to be suggesting that the compiler thinks your lambda *accepts* an integer parameter even though it simply captures *this* and *i*. Are you absolutely sure the code posted is the code that's causing the error? It works just fine for me. – G.M. Aug 04 '17 at 09:36
  • Try explicitly using the static method: `QObject::connect(....)`. @G.M. Question was edited it seems, and now it looks like the code and error message are not in sync... – hyde Aug 04 '17 at 09:38
  • You really should pass `this` as a context object (third argument, before the lambda) if you're capturing `this` - otherwise the lambda may be called after `this` has been destroyed. – Toby Speight Aug 04 '17 at 09:39
  • @hyde My bad -- I should've checked the edits. But, I agree, it does appear the code/error are out of sync. – G.M. Aug 04 '17 at 09:46

2 Answers2

2

Your connection is wrong. You can't connect a function that doesn't take parameters (clicked()) with a function that takes parameters (your lambda). To verify that this is the case, just do this:

connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this](){});

And see that it will compile. You have to make your design in such a way that signals and slots are compatible.

Also avoid using lambdas in signals and slots. Read the caveats here.

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • 5
    I wouldn't go as far as saying "avoid lambdas" - just know how they work with signals and slots and use them correctly. Besides, since Qt 5.2 where you can now pass a context object to be used to break the connection to the lambda, the biggest caveat is gone. – Jesper Juhl Aug 04 '17 at 07:53
  • 1
    @JesperJuhl Agreed. But I'm considering that the guy doesn't understand anything about connections (yet), and hoping the link will explain why he should be careful with lambdas. – The Quantum Physicist Aug 04 '17 at 07:55
  • Thanks. With your code, I have the same error. The connection are not recognized. – Liscare Aug 04 '17 at 08:01
  • @TheQuantumPhysicist `C:\Users\lbraud\SW-Provider-GUI\SoftwareUpdater\src\mainwidget.cpp:66: error: no matching function for call to 'SoftwareUdpater::MainWidget::connect(QWidget*, void (QAbstractButton::*)(bool), SoftwareUdpater::MainWidget::displayTable()::)' connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[](){});` – Liscare Aug 04 '17 at 08:08
  • @LilianBr Sorry, I don't know what the problem is. Try to use normal signals and slots. – The Quantum Physicist Aug 04 '17 at 08:51
  • I will use a table to save the position of the button and its pointer, so I will be able to use a normal connection. – Liscare Aug 04 '17 at 09:05
  • 2
    If you really can't make it work with a lambda, you can still use the [QSignalMapper](http://doc.qt.io/qt-5/qsignalmapper.html) to solve your problem I guess, better than using a custom table. – xander Aug 04 '17 at 09:18
  • The problem is that `QWidget *` does not define `clicked`, but`QPushButton *` does. Check my answer for more details. – Tenders McChiken Feb 28 '21 at 18:07
1

I was reading your comments on the accepted answer and noticed the root of the problem: This error is being thrown because the effective type of the object — as supplied to QObject::connect; i.e QWidget in your case — does not define the referenced signal QPushButton::clicked.

What likely happened is that the QPushButton pointer was cast into a QWidget and then that pointer was given to connect instead of the original which defines the signal.

Cast the pointer back to a QPushButton * and the error should go away.

Tenders McChiken
  • 1,216
  • 13
  • 21