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.

p.i.g.
  • 2,815
  • 2
  • 24
  • 41
c0d3L0g1c
  • 111
  • 1
  • 1
  • 5

3 Answers3

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.

Uli Schlachter
  • 9,337
  • 1
  • 23
  • 39
  • 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. – c0d3L0g1c Sep 05 '10 at 11:37
  • What happens after you add Q_OBJECT? How are you compiling your code? – Uli Schlachter Sep 05 '10 at 11:40
  • 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. – c0d3L0g1c Sep 05 '10 at 11:42
  • 1
    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. –  Sep 05 '10 at 12:33
  • 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! – c0d3L0g1c Sep 05 '10 at 12:36
  • 1
    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. – teukkam Sep 05 '10 at 12:36
  • See this question I asked: http://stackoverflow.com/questions/3607262/why-wont-this-compile-link-with-the-q-object-macro-in-place - the solution is the same: rerun qmake – teukkam Sep 05 '10 at 12:37
  • Thanks to Roku and Teukkam, your suggestions worked. How do i award points? :-) – c0d3L0g1c Sep 05 '10 at 12:38
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.

photo_tom
  • 7,292
  • 14
  • 68
  • 116
2

Edited:

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

bruno
  • 2,802
  • 1
  • 23
  • 23
  • I have awarded points to Uli Schlachter, as he did point me in the right direction. Thanks to everyone for contributing! – c0d3L0g1c Sep 05 '10 at 12:42