BricoMaster
BricoMaster

Reputation: 21

Why does my attempt at connecting a pushbutton to a lambda fail?

I have some issues while trying to use lambda expression to make connections between a pushbutton and a function I want to call when I click the button.

I am using Qt 5.6, with the compiler MinGW 4.9.2 (the default one). My code is the following :

In mainwindow.cpp :

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initBuildings();
    initPage();

    for (int i(0); i<buildings.size(); ++i) {
        connect(static_cast<QAbstractButton*>(widgetlist.at(i).at(2)), &QAbstractButton::clicked, [this, i]() {
            buildings.at(i).buy(amountMultiplier);});
    }
}

void MainWindow::initBuildings()
{
    Building b1 = Building("Building 1",100,1,200);
    Building b2 = Building("Building 2",1000,10,2000);
    buildings.append(b1);
    buildings.append(b2);
}

void MainWindow::initPage()
{
    for (int i(0); i<buildings.size(); i++) {
        QList<QWidget *> buttons;
        QLabel *namelabel = new QLabel(buildings.at(i).getName());
        QLabel *amountlabel = new QLabel;
        QPushButton *buybutton = new QPushButton(this);
        QPushButton *upgradebutton = new QPushButton(this);
        amountlabel->setFixedSize(50,40);
        buybutton->setFixedSize(100,40);
        upgradebutton->setFixedSize(100,40);
        buttons.append(namelabel);
        buttons.append(amountlabel);
        buttons.append(buybutton);
        buttons.append(upgradebutton);
        widgetlist.append(buttons);
    }
}

In mainwindow.h :

#include <QMainWindow>
#include <QScrollArea>
#include <QList>
#include <building.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    void initBuildings();
    void initPage();
    Ui::MainWindow *ui;
    int amountMultiplier;
    QList<Building> buildings;
    QList<QList<QWidget*>> widgetlist;
};

And "Building" is a class I have created which does not inherit from another class. The function I want to use is a public funtion of this class:

void buy(int amount) const; 

It doesn't compile and I get several errors :

I tried to change the lambda capture list, or to change the way I get the value in the lists but it doesn't change anything and I don't figure what is the problem. Maybe I am wrong in the use of the lambda ?

Upvotes: 2

Views: 208

Answers (2)

Two problems:

  1. buildings.at() returns a const Building &, and the buy method is not const. You must index the buildings using [] instead.

  2. The type returned from widgetlist.at(i).at(2) is definitely not QPushButton* - if it was, the code would compile. Even the error message indicates what the issue is:

no matching function for call to 'MainWindow::connect(QWidget* const&, void (QAbstractButton::*)(bool), [...])

This compiles:

// https://github.com/KubaO/stackoverflown/tree/master/questions/lambda-list-37615204
#include <QtWidgets>

struct Building {
   void buy() {}
};

class Class : public QObject {
   QList<Building> m_buildings;
   QList<QList<QWidget*>> m_widgets;
public:
   Class() {
      for (int i = 0; i<m_buildings.size(); ++i)
         connect(static_cast<QAbstractButton*>(m_widgets.at(i).at(2)), &QAbstractButton::clicked, [=] {
            m_buildings[i].buy();
         });
   }
};

int main() {}

If you wish an extra measure of safety in face of programming errors on your part, replace the static_cast with a qobject_cast, it'll then abort if you cast a non-button instead of doing something possibly misleading.

Upvotes: 2

arrowd
arrowd

Reputation: 34411

According to the documentation, your lambda should accept a bool argument.

Upvotes: -1

Related Questions