Почему моя попытка подключения кнопки к лямбда не срабатывает?

66
5

У меня есть некоторые проблемы при попытке использовать лямбда-выражение для соединения между кнопкой и функцией, которую я хочу вызвать, когда я нажимаю кнопку.

Я использую Qt 5.6, с компилятором MinGW 4.9.2 (по умолчанию). Мой код следующий:

В 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);
}
}

В 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;
};

И "Строительство" - это класс, который я создал, который не наследуется от другого класса. Функция, которую я хочу использовать, - это публичная функция этого класса:

void buy(int amount) const; 

Он не компилируется, и я получаю несколько ошибок:

    no matching function for call to 'MainWindow::connect(QAbstractButton*, void (QAbstractButton::*)(bool), MainWindow::MainWindow(QWidget*)::<lambda()>) invalid use of incomplete type 'struct QtPrivate::QEnableIf< false, QMetaObject::Connection> cannot convert '<lambda closure object>MainWindow::MainWindow(QWidget*)::< lambda()>{((MainWindow*)this), i}' (type 'MainWindow::MainWindow(QWidget*)::< lambda()>') to type 'const QObject*

Я попытался изменить список захвата лямбды или изменить способ получения значения в списках, но он ничего не меняет, и я не понимаю, в чем проблема. Может быть, я ошибаюсь в использовании лямбда?

спросил(а) 2016-06-03T16:05:00+03:00 4 года, 1 месяц назад
1
Решение
66

Две проблемы:

buildings.at() возвращает const Building & и метод buy не const. Вы должны индексировать здания, используя [] вместо этого.

Тип, возвращаемый из widgetlist.at(i).at(2), определенно не QPushButton* - если бы это было так, то код был бы скомпилирован. Даже сообщение об ошибке указывает, что проблема:

нет соответствующей функции для вызова "MainWindow :: connect (QWidget * const &, void (QAbstractButton :: *) (bool), [...])

Это компилирует:

// 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() {}

Если вы хотите дополнительную меру безопасности в условиях ошибок программирования с вашей стороны, замените static_cast с qobject_cast, он будет затем прервать, если вы разыгрываете не-кнопки вместо того, чтобы делать что - то, возможно, вводит в заблуждение.

ответил(а) 2016-06-03T17:19:00+03:00 4 года, 1 месяц назад
-4

Согласно документации, ваша лямбда должна принять аргумент bool.

ответил(а) 2016-06-03T16:55:00+03:00 4 года, 1 месяц назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема