tags:

views:

86

answers:

3

Hi All

I am new to C++ Qt programming.

Having difficulty with hooking up buttons to signals and events. Not sure what i'm doing wrong, please see code below.

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

Qt output shows 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. Not sure whats up. Any help would be appreciated.

+3  A: 

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
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
What happens after you add Q_OBJECT? How are you compiling your code?
Uli Schlachter
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
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.
Roku
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
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
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
Thanks to Roku and Teukkam, your suggestions worked. How do i award points? :-)
c0d3L0g1c
+1  A: 

Edited:

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

bruno
I have awarded points to Uli Schlachter, as he did point me in the right direction. Thanks to everyone for contributing!
c0d3L0g1c
A: 

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