PDA

View Full Version : Q_OBJECT macro problem



bijan311
14th March 2010, 03:03
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLCDNumber>
#include <QHBoxLayout>
#include <QVBoxLayout>

class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *parent = 0) : QWidget(parent){
minus = new QLabel("-");
equal = new QPushButton("&Execute");
num1 = new QSpinBox;
num2 = new QSpinBox;
answer = new QLCDNumber(3);

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(num1);
layout->addWidget(minus);
layout->addWidget(num2);
layout->addWidget(answer);
QHBoxLayout *buttons = new QHBoxLayout;
buttons->addStretch();
buttons->addWidget(equal);
buttons->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(buttons);
QObject::connect(equal, SIGNAL(clicked()), answer, SLOT(calculate()));
}
public slots:
void calculate() {
answer->display(num1->value()-num2->value());
disconnect();
}
private:
QLabel *minus;
QPushButton *equal;
QPushButton *help;
QSpinBox *num1;
QSpinBox *num2;
QLCDNumber *answer;
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Calculator w;
w.show();
return app.exec();
}

When the compiler is linking to the .exe it gives me this error.


C:\Program Files\CodeBlocks\MinGW\bin\..\lib\gcc\mingw32\3.4. 5\..\..\..\..\include\c++\3.4.5\bits\stl_algobase. h:(.text$_ZN10CalculatorD1Ev[Calculator::~Calculator()]+0xb)||undefined reference to `vtable for Calculator'|


Thank you in advance.

Lykurg
14th March 2010, 06:25
This problem did not occur when your have your class in a separate file. If you make it like you did you have to add

#include "calculator.moc" at the end of your code.

bijan311
14th March 2010, 14:35
I did this and it said


calculator.moc: No such file or directory

and there is no other file in the folder that has the .moc extension, and I have ran qmake in that directory.

Lykurg
14th March 2010, 16:05
Sorry, it has to be the name of your filename. So probably #include "main.moc"

bijan311
14th March 2010, 19:13
ok so i put my fail name and .moc but it gives me the same error.

squidge
14th March 2010, 20:36
copy and paste here the exact line you typed in

ChrisW67
14th March 2010, 23:35
Have you rerun qmake in order for it to pick up the dependency that main.o now has on main.moc?

bijan311
15th March 2010, 00:09
yes I have rerun qmake in the directory of my program

and here is my exact line.


#include "main.moc"

Lykurg
15th March 2010, 09:31
1. show us your file
2. How is your file named?

bijan311
15th March 2010, 22:18
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLCDNumber>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "main.moc"

class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *parent = 0) : QWidget(parent){
minus = new QLabel("-");
equal = new QPushButton("&Execute");
num1 = new QSpinBox;
num2 = new QSpinBox;
answer = new QLCDNumber(3);

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(num1);
layout->addWidget(minus);
layout->addWidget(num2);
layout->addWidget(answer);
QHBoxLayout *buttons = new QHBoxLayout;
buttons->addStretch();
buttons->addWidget(equal);
buttons->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(buttons);
QObject::connect(equal, SIGNAL(clicked()), answer, SLOT(calculate()));
}
public slots:
void calculate() {
answer->display(num1->value()-num2->value());
disconnect();
}
private:
QLabel *minus;
QPushButton *equal;
QPushButton *help;
QSpinBox *num1;
QSpinBox *num2;
QLCDNumber *answer;
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Calculator w;
w.show();
return app.exec();
}

my file is called main.cpp

norobro
15th March 2010, 22:50
Reread Lykurg's post (#2) above about where your "#include main.moc" should go.

bijan311
19th March 2010, 23:25
you mean this?


#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLCDNumber>
#include <QHBoxLayout>
#include <QVBoxLayout>

class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *parent = 0) : QWidget(parent){
minus = new QLabel("-");
equal = new QPushButton("&Execute");
num1 = new QSpinBox;
num2 = new QSpinBox;
answer = new QLCDNumber(3);

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(num1);
layout->addWidget(minus);
layout->addWidget(num2);
layout->addWidget(answer);
QHBoxLayout *buttons = new QHBoxLayout;
buttons->addStretch();
buttons->addWidget(equal);
buttons->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(buttons);
QObject::connect(equal, SIGNAL(clicked()), answer, SLOT(calculate()));
}
public slots:
void calculate() {
answer->display(num1->value()-num2->value());
disconnect();
}
private:
QLabel *minus;
QPushButton *equal;
QPushButton *help;
QSpinBox *num1;
QSpinBox *num2;
QLCDNumber *answer;
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Calculator w;
w.show();
return app.exec();
}
#include "main.moc"

if so I get the same error.

norobro
20th March 2010, 00:55
My steps:

Copy code from your post
Paste into a file named main.cpp
run qmake -project
run qmake
run make
See the results in the attachment.

You will still get a no such slot warning though.

bijan311
20th March 2010, 01:41
ok I did that but when I built it it gave the same error I think it has something to do with the last line

norobro
20th March 2010, 02:59
The code is fine. It compiled on my Linux box.
Might be a problem with your mingw installation. Someone familiar with windows should be able to help you out.

Lykurg
20th March 2010, 06:12
it seems you are not using the mingw installation which is bundled with the sdk. Are you using Code::Blocks? then just add the right path to Qt's MinGW in the PATH variable.

bijan311
20th March 2010, 15:42
how do I do that

Lykurg
20th March 2010, 17:33
Please try first to compile your application under the Qt console. Something like "Start->Qt X.X.X->Console". There change to your directory and run qmake and mingw32-make. Does it compile?

bijan311
20th March 2010, 18:48
the last line says
"mingw32-make: *** [debug] ERROR 2"

bijan311
21st March 2010, 15:06
I think the problem is I don't know how to make a .moc file

squidge
21st March 2010, 17:23
You don't need to make a .moc file, the #include statement on it's own is sufficient.

norobro
21st March 2010, 18:03
Did you set your path? Installing Qt on Windows (http://doc.qt.nokia.com/4.6/install-win.html)

bijan311
21st March 2010, 19:17
I went to Control Panel|System|Advance System Settings | Environmental Variables...|Path then typed in c:/qt/4.6.2/bin and nothing new happened.

norobro
21st March 2010, 19:50
I downloaded Qt for windows out of curiosity. During the installation I told it to install in a directory named "d:/qt". The moc executable (moc.exe) ended up in "d:/qt/qt/bin". There is also a "d:/qt/bin". So your path might be "c:/qt/4.6.2/qt/bin". Check to see where "moc.exe" is on your machine and put that in your path.

Lykurg
21st March 2010, 21:30
Since the windows sdk is build with two different compilers ":/qt/4.6.2/bin" is only for Qt creator, whereas :/qt/4.6.2/qt/bin is the normal bin directory of Qt.

bijan311
22nd March 2010, 01:47
No matter what I do this still happens, maybe someone could attach a video to show me what to do.

fe
22nd March 2010, 03:05
Well, i'm a brazilian guy !
So, excuses goes for my poor english.

My first contact with trolls and qt, was in february 2010. I am a very very very newbie.

I am now, just wating the result of this thread.
It is because i have installed qt creator into a linux (fedora 12) box, and noted the same situation described here.

just proceed as follow

1- Start a new EMPTY qt project.
2 - Add main.cpp
3 - Subclass any qt class and use QT_OBJECT macro.
4. build

The same error will ocurr.

But if i start a non-empty project, delete all files, and then re-start adding main.cpp, the build goes right.

Someone has any clue ?

fe

squidge
22nd March 2010, 07:02
This works for me, please attach your project where this error occurs.

fe
22nd March 2010, 16:48
I must reformulate my post, because i was totally wrong.

The error occurs *ONLY* if i subclass inside main.cpp.
Today a just started a empty Qt project an typed the following "do nothing" main.cpp :

#include <QApplication>
#include "SubclassE.h"

class SubclassI : public QWidget
{
Q_OBJECT
public:
SubclassI(QWidget *parent = 0) : QWidget(parent) {} ;

} ;

int main(int argc, char *argv[])
{
SubclassE e ;
SubclassI i ;
QApplication a(argc, argv);

return a.exec();
}

The SubclassE.h defines a class similar to SubclassI defined in the main.cpp. Here is my SubclassE.h

#ifndef SUBCLASSE_H
#define SUBCLASSE_H
#include <QWidget>

class SubclassE : public QWidget
{
Q_OBJECT
public:
SubclassE(QWidget *parent = 0) : QWidget(parent) {} ;

} ;

#endif // SUBCLASSE_H


Then, when i build, the SubclassE pass through the compiler, but SubclassI (defined into main.cpp) generates
the error :

undefined reference to 'vtable SubclassI'

I searched into examples code by a project that uses a subclass with Q_OBJECT macro inside main.cpp.
I found moveblocks.

The strange fact is that moveblocks compilation generates no errors. I saw a main.moc after the moveblocks build. That file is not generated when i build my own project. But a moc_SubclassE.cpp was generated.

Now, the question really is :

Why no main.moc is generated after my build ?

thanks,
fe.

PS : I don't know how to put the code inside this box with that amazing colors and scrollbar.

squidge
22nd March 2010, 17:32
For full example, the following main.cpp will both compile and link. Your SubclassE.h does not need to be modified.



#include <QApplication>
#include "SubclassE.h"

class SubclassI : public QWidget
{
Q_OBJECT
public:
SubclassI(QWidget *parent = 0) : QWidget(parent) {} ;

} ;

int main(int argc, char *argv[])
{
SubclassE e ;
SubclassI i ;
QApplication a(argc, argv);

return a.exec();
}

#include "main.moc"


When run, it produces the following:



Starting example.exe...
QWidget: Must construct a QApplication before a QPaintDevice


Which is expected, as you attempt to create an instance of SubclassE and SubclassI before QApplication.

norobro
22nd March 2010, 17:59
PS : I don't know how to put the code inside this box with that amazing colors and scrollbar.Click the "Go Advanced" tab. Then hover over the icons above the text box to see what each icon provides. e.g."#" is for code.

norobro
22nd March 2010, 19:31
@bijan311 - Please post the start up screen for your Qt Command Prompt. 4437

fe
22nd March 2010, 20:00
Yeah !

Thanks norobro !

I put the #include "main.moc" and build tell me that main.moc was not found.
Then i clean the project, run qmake and rebuild it.

There is no error now.

bijan311
22nd March 2010, 21:48
ok, here you go.

I have no idea why the thing on top is green, its usually blue

squidge
22nd March 2010, 23:01
Why is Qt trying to add the codeblocks directory to the PATH?

Maybe it's trying to use the wrong version of gcc?

A bit heavy handed, but have you tried uninstalling CodeBlocks and then reinstalling the Qt SDK and then using Qt Creator on your project?

norobro
22nd March 2010, 23:57
Sorry bijan311 I've just been shooting in the dark. I haven't used windows for several years and this is my first stab at using Qt under windows. Heck I had to squirt a little wd40 onto my winxp to get it to boot:)

Looks to me like the path still isn't right. Notice that my path is set to d:\Qt\4.6.2\qt\bin. That's where moc.exe resides on my system. I have no idea how it was set if changing the path in environment variables didn't change yours.

Fatjuicymole is a windows user so I'd follow his advice.

squidge
23rd March 2010, 07:54
My post is a complete stab in the dark too, but it just seems weird that since Qt comes with GCC, why it would use the GCC in the Codeblocks directory.

bijan311
24th March 2010, 22:45
Maybe because my MinGW installment is in the Codeblocks directory

bijan311
26th March 2010, 05:02
Ok I found "main.moc" in the debug folder so I copied that into the folder that main.cpp is in, but when i compiles and i press execute the LCDNumber doesn't change.
here is my code


#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLCDNumber>
#include <QHBoxLayout>
#include <QVBoxLayout>

class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *parent = 0) : QWidget(parent){
minus = new QLabel("-");
equal = new QPushButton("&Execute");
num1 = new QSpinBox;
num2 = new QSpinBox;
answer = new QLCDNumber(3);

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(num1);
layout->addWidget(minus);
layout->addWidget(num2);
layout->addWidget(answer);
QHBoxLayout *buttons = new QHBoxLayout;
buttons->addStretch();
buttons->addWidget(equal);
buttons->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(buttons);
QObject::connect(equal, SIGNAL(clicked()), answer, SLOT(calculate()));
}
public slots:
void calculate() {
answer->display(num1->value()-num2->value());
disconnect();
}
private:
QLabel *minus;
QPushButton *equal;
QPushButton *help;
QSpinBox *num1;
QSpinBox *num2;
QLCDNumber *answer;
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Calculator w;
w.show();
return app.exec();
}
#include "main.moc"

squidge
26th March 2010, 07:54
Your connect call is still wrong. Your answer object doesn't have a slot called calculate.

bijan311
26th March 2010, 15:23
but its in public slots

Archimedes
26th March 2010, 15:33
It's in the public slots of class Calculator and NOT of class QLCDNumber. So change your connect statement to this:

QObject::connect(equal, SIGNAL(clicked()), this, SLOT(calculate()));

bijan311
26th March 2010, 16:00
thanks so much

bijan311
26th March 2010, 16:40
wait... now I changed the code up a bit and I think need to update the .moc file but can't find out how
he is main.cpp


#include <QApplication>
#include "calc.h"

int main(int argc, char **argv){
QApplication app(argc, argv);
Calculator w;
w.show();
return app.exec();
}
#include "main.moc"

and calc.h


#ifndef CALC_H
#define CALC_H

#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLCDNumber>
#include <QHBoxLayout>
#include <QVBoxLayout>

class Calculator : public QWidget {
Q_OBJECT
public:
Calculator(QWidget *parent = 0) : QWidget(parent){
minus = new QPushButton("&-");
add = new QPushButton("&+");
multiply = new QPushButton("&X");
divide = new QPushButton("&/");
num1 = new QSpinBox;
num2 = new QSpinBox;
answer = new QLCDNumber(3);

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(num1);
layout->addWidget(num2);
layout->addWidget(answer);

QHBoxLayout *button1 = new QHBoxLayout;
button1->addStretch();
button1->addWidget(add);
button1->addWidget(minus);
button1->addStretch();

QHBoxLayout *button2 = new QHBoxLayout;
button2->addStretch();
button2->addWidget(multiply);
button2->addWidget(divide);
button2->addStretch();


QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addLayout(button1);
mainLayout->addLayout(button2);

connect(minus, SIGNAL(clicked()), this, SLOT(subtract()));

}
public slots:
void subtract(){
answer->display(num1->value()-num2->value());
disconnect();
}
void plus(){
answer->display(num1->value()+num2->value());
}
void times(){
answer->display(num1->value()*num2->value());
}
void divider(){
answer->display(num1->value()/num2->value());
}
private:
QPushButton *minus;
QPushButton *add;
QPushButton *multiply;
QPushButton *divide;
QPushButton *help;
QSpinBox *num1;
QSpinBox *num2;
QLCDNumber *answer;
};
#endif CALC_H

squidge
26th March 2010, 18:08
You don't need the #include anymore as your class is in a header file now. Just run qmake.

bijan311
26th March 2010, 19:44
but if i take out


#include "main.moc"

I get this error


C:\MinGW\include\c++\3.4.5\bits\stl_algobase.h:(.t ext$_ZN10CalculatorD1Ev[Calculator::~Calculator()]+0xb)||undefined reference to `vtable for Calculator'|

squidge
26th March 2010, 22:21
Yes, which is why you need to run qmake, to update the project file to resolve that error.