2016-06-03 3 views
2

Ich habe einige Probleme beim Versuch, Lambda-Ausdruck zu verwenden, um Verbindungen zwischen einer Drucktaste und einer Funktion herzustellen, die ich aufrufen möchte, wenn ich auf die Schaltfläche klicke.Warum schlägt mein Versuch, eine Drucktaste mit einem Lambda zu verbinden, fehl?

Ich verwende Qt 5.6, mit dem Compiler MinGW 4.9.2 (der Standard). Mein Code ist der folgende:

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

und "Gebäude" ist eine Klasse, die ich geschaffen habe, die nicht von einem anderen nicht erben Klasse. Die Funktion, die ich verwenden möchte, ist eine öffentliche funtion dieser Klasse:

void buy(int amount) const; 

Es lässt sich nicht kompilieren und ich mehrere Fehler:

  • 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*

Ich habe versucht, die Lambda Capture-Liste zu ändern, oder die wa zu ändern y Ich bekomme den Wert in den Listen, aber es ändert nichts und ich sehe nicht, was das Problem ist. Vielleicht liege ich falsch in der Verwendung des Lambda?

+0

Welcher Typ ist meine Liste? – CppChris

+0

Bitte zeigen Sie uns die Deklaration der 'MainWindow :: connect' Funktion – PcAF

+0

@PcAF Es ist' QObject :: connect': http://doc.qt.io/qt-5/qobject.html # connect-4 –

Antwort

-1

Gemäß the documentation sollte Ihr Lambda ein bool Argument akzeptieren.

+0

Es muss nicht. Funktoren/Slots, die mit einem Signal verbunden sind, können eine beliebige Anzahl von nachfolgenden Argumenten ignorieren, einschließlich aller von ihnen. –

2

Zwei Probleme:

  1. buildings.at() gibt ein const Building & und die buy Methode ist nicht konst. Sie müssen die Gebäude stattdessen indizieren, indem Sie [] verwenden.

  2. Der Typ von widgetlist.at(i).at(2) zurückgekehrt ist definitiv nicht QPushButton* - wenn es ist, würde der Code kompiliert. Auch gibt die Fehlermeldung, was das Problem ist:

keine passende Funktion für Aufruf von ‚Mainwindow :: connect (QWidget * const &, void (QAbstractButton :: *) (Bool) [...])

Dies kompiliert:

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

Wenn Sie wünschen Sie ein zusätzliches Maß an Sicherheit angesichts von Programmierfehlern Ihrerseits, ersetzen Sie die static_cast durch eine qobject_cast, es wird dann abbrechen, wenn Sie eine Nicht-Schaltfläche, anstatt etwas irreführend zu tun.

+0

Danke für die schnelle Antwort! Aber selbst mit den von Ihnen vorgeschlagenen Änderungen gibt es den gleichen Fehler. Ich habe den statischen_cast gemacht, aber das Ergebnis ist das gleiche. "keine passende Funktion für den Aufruf von 'MainWindow :: connect (QAbstractButton *, void (QAbstractButton :: *) (bool), MainWindow :: MainWindow (QWidget *) :: )'" – BricoMaster

+1

@BricoMaster Der Code ich oben zeigen funktioniert. Das ist dein Ausgangspunkt. Fügen Sie es in ein neues Projekt ein und stellen Sie sicher, dass es dort funktioniert. Vielleicht ist dein Compiler kaputt? Vielleicht machst du etwas anderes? Bitte bearbeiten Sie Ihre Frage mit ** vollständigem Code, der für Sie scheitert **. Du solltest etwas wie oben in meiner Antwort gepostet haben - es ist deine grundlegende Pflicht, wenn du eine Frage zu SO stellst! Es ist eine sogenannte Minimierung Ihres Problems: alles Irrelevante wurde verworfen. Ich musste deinen Code erraten, weil deine Frage mangelhaft ist. –

+0

Ich stimme zu, es kann schwierig sein, eine Antwort ohne den Kontext zu erraten. Ich habe die Frage mit dem vollständigen Code bearbeitet. Mit dem Fehler, den ich bekomme, scheint es, als ob es keine Funktion "verbinden" mit Lambda gibt, auch wenn die Dokumentation sagt, dass es möglich ist. – BricoMaster

Verwandte Themen