C++ Qt signal and slot not firing
Asked Answered
S

3

10

I am having difficulty in my Qt program with connecting button signals to my slots. My code is:

Main.cpp

#include <QtGui/QApplication>
#include "MainWidget.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MainWidget mainWidget;
    mainWidget.show();

    return app.exec();
}

MainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

class MainWidget : public QWidget
{
public:
    MainWidget();

public slots:
    void bAdvice_clicked();
    void bWeather_clicked();
    void bNextMeeting_clicked();
    void bQuit_clicked();
};

#endif // MAINWIDGET_H

MainWidget.cpp

#include "MainWidget.h"
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>

MainWidget::MainWidget()
{
    QLayout *layout = new QVBoxLayout();
    this->setLayout(layout);

    QTextEdit *message = new QTextEdit();
    layout->addWidget(message);

    QPushButton *bAdvice = new QPushButton("Advice");
    connect(bAdvice, SIGNAL(clicked()), this, SLOT(bAdvice_clicked()));
    layout->addWidget(bAdvice);

    QPushButton *bWeather = new QPushButton("Weather");
    connect(bWeather, SIGNAL(clicked()), this, SLOT(bWeather_clicked()));
    layout->addWidget(bWeather);

    QPushButton *bNextMeeting = new QPushButton("Next Meeting");
    connect(bNextMeeting, SIGNAL(clicked()), this, SLOT(bNextMeeting_clicked()));
    layout->addWidget(bNextMeeting);

    QPushButton *bQuit = new QPushButton("Quit");
    connect(bQuit, SIGNAL(clicked()), this, SLOT(bQuit_clicked()));
    layout->addWidget(bQuit);
}

void MainWidget::bAdvice_clicked()
{
}

void MainWidget::bWeather_clicked()
{
}

void MainWidget::bNextMeeting_clicked()
{
    QMessageBox::information(this, "Next Meeting", "Today", QMessageBox::Ok);
}

void MainWidget::bQuit_clicked()
{
    this->close();
}

The program outputs the following:

Starting C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe...
Object::connect: No such slot QWidget::bAdvice_clicked() in MainWidget.cpp:16
Object::connect: No such slot QWidget::bWeather_clicked() in MainWidget.cpp:20
Object::connect: No such slot QWidget::bNextMeeting_clicked() in MainWidget.cpp:24
Object::connect: No such slot QWidget::bQuit_clicked() in MainWidget.cpp:28

C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe exited with code 0

The code seems right, no compiler warnings. Just this output at runtime. But it looks like I hooked the signals and slots up correctly.

Sip answered 5/9, 2010 at 11:27 Comment(0)
T
16

Add Q_OBJECT to your class, like this:

class MainWidget : public QWidget
{
    Q_OBJECT

You also have to run moc to generate some helper code. qmake does that automatically for your, but if you compile this yourself, you need to run moc.

Themselves answered 5/9, 2010 at 11:33 Comment(8)
Thanks for the quick response. But can you please be more specific as i am very new to this. I have changed my code to add Q_OBJECT immediately after the open curly braces. Still the same result. I am using Qt Creator IDE.Sip
What happens after you add Q_OBJECT? How are you compiling your code?Themselves
I have changed my code to add Q_OBJECT immediately after the open curly braces. Still the same result. I am using Qt Creator IDE.Sip
Delete all the Makefiles (Makefile, Makefile.Debug and Makefile.Release) from your project directory and recompile. Now the QMake is executed and signals should now be working.Abydos
I cleaned the build and rebuilt with Q_OBJECT. Now i get build issues saying undefined reference to `vtable for MainWidget'. I hope this sheds more light on the topic. It does however seem related to MOC. How do i get Qt Creator to auomatically handle this? Please help!Sip
You don't need to delete anything, just rerun qmake after adding the Q_OBJECT macro has been added. In Qt Creator it can be done from the build menu.Governor
See this question I asked: #3607762 - the solution is the same: rerun qmakeGovernor
Thanks to Roku and Teukkam, your suggestions worked. How do i award points? :-)Sip
F
3

When I started with Qt, I had this problem a lot. As I see it your slots are defined wrong. If you look at the signature for the signal (Qt Clicked Signal Docs), you will see that the argument list is (bool clicked = false).

The way Qt's signal & slots connect work at run time, is that it will only connect the signal and slot if they have the exact same signatures. If they don't match exactly, no connection.

so in MainWidget.h

 public slots:
        void bAdvice_clicked(bool);

In MainWidget.cpp

  connect(bAdvice, SIGNAL(clicked(bool)), this, SLOT(bAdvice_clicked(bool)));

Things will start working for you.

Fiche answered 5/9, 2010 at 21:57 Comment(1)
but i get that works for QPushButton without the bool type parameterShiverick
M
2

Edited:

Compiled your code and all the slots were correctly called. It was just the Q_OBJECT macro that was missing.

Mazda answered 5/9, 2010 at 12:27 Comment(1)
I have awarded points to Uli Schlachter, as he did point me in the right direction. Thanks to everyone for contributing!Sip

© 2022 - 2024 — McMap. All rights reserved.