Error: no matching function for call to 'QObject::connect



  • Hi,

    I'm building a simple program to learn how to use widgets, layouts, etc without using the designer but ran through a problem. Basically, the program is designed to have a typical main and MainWindow but instead of having all gui code in MainWindow, I have a class called MainWindowContent which builds the gui and returns the layout containing all the widgets which is added to MainWindow's central widget.

    #include "mainwindowcontent.h"
    
    MainWindowContent::MainWindowContent()
    {
    
    }
    
    QGridLayout* MainWindowContent::getPageWidgetsLayout()
    {
        QGridLayout *gridLayout  =new QGridLayout();
    
        QLabel *label = new QLabel("");
    
        QLineEdit *lineEdit = new QLineEdit("Enter Text!");
    
        QPushButton *button = new QPushButton("OK!");
    
        QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton(label, lineEdit)));
    
        gridLayout->addWidget(label,0,0);
        gridLayout->addWidget(lineEdit,1,1);
        gridLayout->addWidget(button,2,2);
       
    
        return gridLayout;
    }
    
    //slot to handle button clicks
    void MainWindowContent::handleButton(QLabel* label,QLineEdit *lineEdit)
    {
        label->setText(lineEdit->text());
    }
    
    

    I keep getting

    error: no matching function for call to 'QObject::connect(QPushButton*&, const char*, MainWindowContent*, const char*)'
    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton(label, lineEdit)));


  • Qt Champions 2016

    @WhatIf said in error: no matching function for call to 'QObject::connect:

    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton(label, lineEdit)));

    Hi
    That is not correct.
    The clicked() signal do not have a label and lineEdit as parameters so you cannot connect like that.
    the signal must have those parameters too.

    Can i ask what the logic should be ?



  • Even if I delete the parameters label and lineEdit from the slot, its function implementation and in the .h file, I still get the same error.



  • @WhatIf,

    Show us the updated header declaration, updated connect call, and the resulting error message.

    Cheers.



  • QObject::connect(button, &QPushButton::clicked,this, std::bind(&MainWindowContent::handleButton,this,label,lineEdit));

    https://wiki.qt.io/New_Signal_Slot_Syntax



  • private slots:
        void handleButton();
    
    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));
    
    void MainWindowContent::handleButton()
    {
        //label->setText(lineEdit->text());
    }
    

    error: no matching function for call to 'QObject::connect(QPushButton*&, const char*, MainWindowContent*, const char*)'
    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));

    I also tried

    QObject::connect(button, &QPushButton::clicked,this, std::bind(&MainWindowContent::handleButton,this,label,lineEdit));
    

    and got

    error: no matching function for call to 'QObject::connect(QPushButton*&, void (QAbstractButton::)(bool), MainWindowContent, std::_Bind_helper<false, void (MainWindowContent::)(QLabel, QLineEdit*), MainWindowContent*, QLabel*&, QLineEdit*&>::type)'
    QObject::connect(button, &QPushButton::clicked,this, std::bind(&MainWindowContent::handleButton,this,label,lineEdit));



  • Hi, maybe you forgot to inherit from QObject or QWidget, i.e. your mainwindowcontent.h should look something like this:

    #pragma once
    #include "qobject.h"
    
    class MainWindowContent : QObject
    {
         Q_OBJECT
    
    public:
        MainWindowContent();
    
    private slots:
        void handleButton(QLabel* label,QLineEdit *lineEdit);
    }
    


  • @WhatIf said in error: no matching function for call to 'QObject::connect:

    I also tried
    QObject::connect(button, &QPushButton::clicked,this, std::bind(&MainWindowContent::handleButton,this,label,lineEdit));

    and got

    error: no matching function for call to 'QObject::connect(QPushButton*&, void (QAbstractButton::)(bool), MainWindowContent, std::_Bind_helper<false, void (MainWindowContent::)(QLabel, QLineEdit*), MainWindowContent*, QLabel*&, QLineEdit*&>::type)'
    QObject::connect(button, &QPushButton::clicked,this, std::bind(&MainWindowContent::handleButton,this,label,lineEdit));

    read the error. (MainWindowContent::)(QLabel, QLineEdit*) did you forget a * next to QLabel in handleButton?



  • I forgot to subclass QObject!

    Now the program compiles but the slot is never called. here is how the code looks at this point.

    signals:
    
    private slots:
        void handleButton(); //handles button clicks
    
    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));
    
    void MainWindowContent::handleButton()
    {
        qDebug() << "INSIDE SLOT!";
    }
    

  • Qt Champions 2016

    Hi
    try with
    qDebug () << "conn:" << QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));
    and see it says
    conn: true



  • Hi, also to add to @mrjj, perhaps the slot is never called because the button isn't visible, you could try insert a show() just after you've created the button, say like this:

    QPushButton* button = new QPushButton("OK!");
    button->show();
    
    QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));


  • qDebug () << "conn:" << QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));
    

    shows conn: true

    using button->show(); doesn't change anything.

    Basically, main.cpp calls mainwindow.cpp to get the central widget. mainwindow.cpp in turn calls mainwindowcontent.cpp to get the layout to set as centralwidget's.

    I'm passing "this" (connect 3rd argument) of mainwindowcontent.cpp to the connect statement.

    Will this make the connect work when mainwindowcontent.cpp returns the layout to mainwindow.cpp?


  • Lifetime Qt Champion

    Hi,

    Did you check whether you have any warning at run time ?

    How do you know it's not getting called ? Did you put a breakpoint in your slot or a qDebug statement ?



  • No warnings at run time.

    I used both breakpoints and a qDebug statement.


  • Lifetime Qt Champion

    Then a silly question: how are you ensuring that you are clicking on the correct button ?



  • There is only one button



  • Hi, just guessing, but how do you assign the grid layout into the centralwidget in your mainwindowp.cpp, is it something similar to this:

    ...
    setCentralWidget(new QWidget());
    centralWidget()->setLayout(mainWindowContent->getPageWidgetsLayout());
    ...
    


  • What's the lifetime of your MainWindowContent instance?

    It looks to me that MainWindowContent::getPageWidgetsLayout() could be entirely static (if you wanted it to be) except for the this in the connect call. So if, for example, your MainWindowContent instance is destroyed, and re-created later, the slot will have been automatically disconnected, and not reconnected.

    Just something else to check...

    Cheers.



  • main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
        w.buildPage(); 
    
        w.show();
    
        return a.exec();
    }
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QLabel>
    #include <QHBoxLayout>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::buildPage()
    {
        MainWindowContent winContent;
    
        ui->centralWidget->setLayout(winContent.getPageWidgetsLayout());
    }
    

    mainwindowcontent.cpp

    #include "mainwindowcontent.h"
    
    #include <QDebug>
    
    MainWindowContent::MainWindowContent(QObject *parent) : QObject(parent)
    {
    
    }
    
    QGridLayout* MainWindowContent::getPageWidgetsLayout()
    {
        QGridLayout *gridLayout  =new QGridLayout();
    
        QLabel *label = new QLabel("");
    
        QLineEdit *lineEdit = new QLineEdit("Enter Text!");
    
        QPushButton *button = new QPushButton("OK!");
    
        QObject::connect(button, SIGNAL (clicked()),this, SLOT (handleButton()));
    
        gridLayout->addWidget(label,0,0);
        gridLayout->addWidget(lineEdit,1,1);
        gridLayout->addWidget(button,2,2);
       
    
        return gridLayout;
    }
    
    void MainWindowContent::handleButton()
    {
        qDebug() << "INSIDE SLOT!";
    }
    


  • The problem is with the winContent lifetime.

    void MainWindow::buildPage()
    {
        MainWindowContent winContent;
    
        ui->centralWidget->setLayout(winContent.getPageWidgetsLayout());
        // at this point, winContent is destroyed, and automatically disconnected.
    }
    

    You probably want to do something more like:

    void MainWindow::buildPage()
    {
        MainWindowContent * winContent = new MainWindowContent(this);
    
        ui->centralWidget->setLayout(winContent->getPageWidgetsLayout());
    }
    

    Or move the slot to the MainWindow class.

    Cheers.



  • Thank you very much for all the help!

    The last problem I have is how to pass the label and lineedit to the slot. I don't want to make them global variables. if I create a custom signal with the label and lineedit to match the slot, I'm confused about where to emit the signal.


  • Lifetime Qt Champion

    Before that, why do you need the MainWindowContent. It looks like a convoluted mean to create the central widget content.



  • I want to keep the logic of how the program progresses from page to page in MainWindow. But I want other classes to generate the pages to be displayed. Basically I want to be able to manage the program without having a single .cpp file that is a thousand lines or so.


  • Lifetime Qt Champion

    Then why not make them full QWidget derivative ?

    That's what is usually done, cut your application in logical pieces and then build as many QWidget based classes as needed to keep the code clean, simple and tidy.



  • Can you give an example please? Or direct me to any tutorial on the topic?


  • Lifetime Qt Champion

    The scribble example is a simple example to start with.



  • I went over the example but I still have some difficulty converting it to my use. I created a MainWindowContent that is a subclass of QWidget and created a

    QGridLayout* MainWindowContent::getPageWidgetsLayout()
    

    the exact same function I provided in the code above.

    I don't think that this is the intended goal of this example because in MainWindow an instance of the QWidget subclass (ScribbleArea) is passed to setCentralWidget not a call to a function using the instance. Am I supposed to move all the code from getPageWidgetsLayout() to the constructor and declare the label, lineedit, and pushbutton as private variables.


  • Lifetime Qt Champion

    No the example shows what I suggested: create a separated widget that encapsulates the functionality of interest and use that one in the MainWindow.



  • Finally, I got it to work but I still have the same problem that I started with. How do I pass the line edit and label to the slot?

    I searched online and all the examples have a condition other than the button being clicked that emit the signal . Any hints please?




Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.