PDA

View Full Version : Creating slots with Q_OBJECT



VireX
13th January 2007, 22:58
Hey all,
I have been using DevC++ Windows QT 4.2.2 to make a class that has my own slot which i can use to make my own event handlers. However, everytime i include Q_OBJECT macro in the class, it creates linker errors such as vtable bla bla, and also I have read while searching these forums some information about moc, which i don't understand at all. Something about including mocs? Well anyway I use a template for DevC++ that someone had made before, i'll include that so you can see whether this moc stuff was made already or maybe you can edit it so that i won't have to do anything else dealing with moc.



[Template]
ver=1
Name=Qt
Icon=Qt.ico
Description=Create a GUI using the Qt library.
Catagory=GUI

[Unit0]
CppName=main.cpp
Cpp=qt_cpp.txt

[Project]
UnitCount=1
Type=1
IsCpp=1
CppCompiler=-O2 -O2 -frtti -fexceptions -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -I"C:/Qt/4.2.2/include/QtGui" -I"C:/Qt/4.2.2/include/QtCore" -I"C:/Qt/4.2.2/include" -I"." -I"C:/Qt/4.2.2/include/ActiveQt" -I"tmp\moc\release_shared" -I"." -I"C:\Qt\4.2.2\mkspecs\win32-g++"
Linker=-mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -Wl,-s -Wl,-subsystem,windows -L"C:\Qt\4.2.2\lib" -L"C:\Qt\4.2.2\lib" -lmingw32 -lqtmain -lQtCore4 -lQtGui4
ProjectIcon=Qt.ico



I'm very new to Qt, but so far I like it better than wxWidgets, except for the event handling since compiling this stuff with connect() and slots/signals has taken many hours to figure out and i still can't get it to work. To get Qt ready, i just downloaded the latest exe file and installed it to my system.

Here's my code example:


class MyWidget : public QWidget
{
Q_OBJECT
public slots:
void TestSlot();
public:
QMessageBox* Box;
MyWidget(QWidget *parent = 0);

};
void MyWidget::TestSlot(){
Box->show();
}
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
QPushButton *quit = new QPushButton(tr("Quit"));
quit->setFont(QFont("Times", 18, QFont::Bold));
QPushButton *Message = new QPushButton(tr("Message"));
Message->setFont(QFont("Times", 18, QFont::Bold));
Box = new QMessageBox(QMessageBox::Information, tr("Hey"), tr("Hi director"),
QMessageBox::Ok, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint );
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(Message, SIGNAL(clicked()), this, SLOT(TestSlot()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(quit);
layout->addWidget(Message);
setLayout(layout);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
widget.setToolTip("A nice little tooltip");
QTabWidget* Tab = new QTabWidget();
Tab->addTab(&widget, "A Tab");
Tab->setToolTip("This is a Tab!");
Tab->show();
return app.exec();
}

Don't worry about the includes, i just didn't write it down here... but they exist.
And yes, I know that I could have attached the slot to the Box itself (messagebox), and then used the public slot "show()"... but I want to test custom slots first.

Thanks for your help + time.
EDIT: Oh one more thing.
When I do compile my programs, the program will not run unless mingwm10.dll QtCore4.dll and QtGui4.dll are in the same folder. I thought that with the template it would compile with the libraries and DLLs would not be required, is there a way to edit the DevC++ template to not use DLLs and to compile them all into the file?

camel
13th January 2007, 23:36
Hi,

I sadly have no idea about DevC++ so I cannot help you there, but maybe I can try to help you with this:


everytime i include Q_OBJECT macro in the class, it creates linker errors such as vtable bla bla, and also I have read while searching these forums some information about moc, which i don't understand at all. Something about including mocs?

As you know Qt has these nice introspection properties. You can call signals and slots just by knowing their name, (and you can query them during runtime if you like). This needs some data and functions to work, which is generated by the Meta Object Compler, and included with the Q_OBJECT macro.

When you include the Q_OBJECT macro, it will be replaced with a block of code that includes this(in Qt 4.2.2)


public:
static const QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const;
private:


The staticMetaObject contains the description of the class. The name and which signals, slots and properties it contains.
The metaObject function is a possibility to look up what kind of object you have exactly, if the only thing you know is that it is a subclass of QObject.

The problem of course is that this function and method need to be defined someplace, and this is in the output of the MOC.

If you do not compile this output and link it into the final library/app the linker will see that there have been some declaration for functions and data, but it cannot find the real thing anywhere, at which point it complains.

The vtable, i.e. the table where c++ stores the information which implementation of virtual functions to use, is created only in the translation unit, i.e. cpp file in most cases, where the first virtual function is defined. Since it is customary to have the Q_OBJECT macro as first thing in the new class, the metaobject() function will always fit this this description and the vtable will always be generated in its translation unit.
This means that if the file where the metaobject functions was defined (i.e. the output of moc) was not compiled and linked in, you get this vtable error.


I hope I could help destroy a bit the magic of the moc error messages, and If you already knew what I was blabbering here, please forgive and just ignore it :-)

Good luck with your main question though. But allow just a hint. (The following is valid for qmake based projects):
Normally, the result of MOCing is only included automatically if the class was defined in a header. If you define a class in a cpp file such as you have, something checks for the line

#include "filename.moc"
(which is usually at the bottom of the cpp file, for practical reasons) and then adds the filename.cpp to the to-be-moc-ed files, and generates filename.moc.

Perhaps it works for you too :-)

Moppel
13th January 2007, 23:48
Hi VereX,

normally you don't have to deal with moc. I prefer to have qmake generating my Makefiles using *.pro files as input.
IIRC the mingwm10.dll is only needed if threading is used. But I guess you don't want to disable thread support.
How to compile and use Qt statically is described here:
http://doc.trolltech.com/4.2/deployment-windows.html



TEMPLATE = app
TARGET = widgt
DEPENDPATH += .
INCLUDEPATH += .

# Input
SOURCES = main.cpp mywidget.cpp

HEADERS = mywidget.h


Have you everything in one file? That wouldn't work.

VireX
14th January 2007, 02:56
It becomes extremely annoying when I have to deal with things like qmake and nmake, which I have dealt with in linux, and it's extremely annoying to do. Which is why i found the template file, which should have done all this for me. I even tried an example i found right out of the documentation of trolltech, and not anywhere did i see a #include moc, or any other compiler options to be set anywhere. It would be easier if there was something I could do, so that I wouldn't have to do this. I do not understand the link you have sent me, now unless I spend 2 hours reading every little document about it, I won't be able to build this.

From what you've told me, all I understand is that Qt has some extra things that needs to be done in order to understand things like "emit" "slots" "signals" and instead of them doing all the work in some header file, as I've seen in windows (excuse me for saying, but my only GUI experience is HEAVY and Lengthy use of Win32 API, which is difficult and buggy, so I used Qt hoping it would be easier, but with all these external libraries and compile this and use this program to attach this and that , it becomes more of a hassle than a helpful library), I have to now do something in order to compile these moc files, which I don't even know where they come from or what makes them... I'm suppose to include something that doesn't exist...

I usually use Visual Studio .NET 2003, but it can get very very annoying when setting up the settings, and the template file I thought handled most of it, but it seems I still have 3 bulky DLLs which i don't know how to link to my program as "lib" or "a" files. So how do I do this? Does anyone have "dummy steps" without going into too much technical detail about the library itself? (keep in mind, that I am only experienced in pure C++ and winAPI not these kinds of libraries etc) How do I make these moc files, and if possible, do you think it can be applied into the DevC++ template file? I also think i don't need the little command that says ActiveQt because I will never use ActiveX anything.

EDIT:
I seperated my file to a .h too.
Ok so I used moc in my bin directory, as such: moc -o QTmain.moc QTmain.h
And it made the moc file, which I then added to my DevC++ project. So I did basically what you guys wanted me to do, which was to have this moc file integrated to my program.

[Linker error] undefined reference to `MyWidget::staticMetaObject'
[Linker error] undefined reference to `vtable for MyWidget'
and i got the same results.

camel
14th January 2007, 04:16
It becomes extremely annoying when I have to deal with things like qmake and nmake, which I have dealt with in linux, and it's extremely annoying to do.

Personally I do not think so.

When I want to compile a project of mine I do

qmake
make
and I am done...


Which is why i found the template file, which should have done all this for me.

Where did you find it? Perhaps you ask the author of the template why it doesn't work as it should?




I even tried an example i found right out of the documentation of trolltech, and not anywhere did i see a #include moc, or any other compiler options to be set anywhere.
The examples use qmake which hides all those nasty things. (If you do not start to digg too deep ;-)

The include trick I mentioned is only needed when you declare a QObject subclass in a cpp file. But that should not normally be needed.




From what you've told me, all I understand is that Qt has some extra things that needs to be done in order to understand things like "emit" "slots" "signals" and instead of them doing all the work in some header file, as I've seen in windows <snip> I have to now do something in order to compile these moc files, which I don't even know where they come from or what makes them... I'm suppose to include something that doesn't exist...
You should not have to care about anything. MOC is an implementation detail that should be abstracted away. It is in qmake, it probably should also for this template, but since I do not work with devc++ I have no idea why it would not.


I usually use Visual Studio .NET 2003, but it can get very very annoying when setting up the settings, and the template file I thought handled most of it, but it seems I still have 3 bulky DLLs which i don't know how to link to my program as "lib" or "a" files.

Allow me the question, why don't you like the dlls? (Just pure curiosity :-)


So how do I do this? Does anyone have "dummy steps" without going into too much technical detail about the library itself?
Does this this (http://www.qtcentre.org/forum/f-newbie-4/t-static-compile-qt4-1233.html) thread help?
In the end you "just" have to reconfigure an rebuild Qt to be static.
(But I do not think that you can loose the mingw dll...but you might want to google that)


How do I make these moc files, and if possible, do you think it can be applied into the DevC++ template file?
Well, I am not too fluid with devc++ but from a (german) article (
http://www.c-plusplus.de/forum/viewtopic-var-t-is-136771-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html) it seems that you have to include a custom makefile/qmake step to have devc++ play nice.


Does it have to be DevC++?
In the Qt Software (http://www.qtcentre.org/forum/f-qt-software-16.html) forum a few native Qt4 IDEs have been posted, which probably know how to work with Qt out of the box. (I cannot give you my word that they work since I am a vi/qmake/make user myself :-)

If you like Visual Studio, the comercial edition of Qt 4 for windows has Visual Studio integration available (at a price though).


Hope that helps...

VireX
14th January 2007, 05:33
Why should I have to figure out how to use qmake, and nmake, when i can just press compile and compile any project I need as long as the project options are set to do everything that you do manually.

I found it online, it's made by some french guy, so I cannot ask him. And it does work, because I am ableto compile and run programs and make them work. But whenever I put Q_OBJECT it causes problems. I don't think thats the fault of the template, but more of the fault of the documents not explaining what to do. Or why they do not have specific tutorials for DevC++/VC++ and other specific compilers, with easy to follow steps that once done, everything should work fine without the users having to spend hours and hours reading thru docs trying to figure out how to just compile..

"You should not have to care about anything. MOC is an implementation detail that should be abstracted away."
I do not use qmake, so I don't know how it is implemented, and I don't understand why it's even there. What am I suppose to do. From what I gathered, this moc file needs to somehow be integrated into my program, so I made the moc file, and i added it to my project, but the error persists, meaning moc wasn't the problem?? or the moc.exe in the bin is buggy or not working? Or there is something else I am required to do other than write "Q_OBJECT" on my classes and add the moc file.

I wish that tutorials were available for QT that wasn't from trolltech, that perhaps had .DEV files or .vc++ files, for VC++ and DevC++. So we do not have to figure this out or use the little qmake stuff. An idea like the template file i showed you, is a great idea, if there was such things for VC++ too that would be great. Well anyway I guess i'll hope someone who knows how moc should be included in the project when NOT using qmake appears, or someone who uses DevC++ to make QT :D

camel
14th January 2007, 13:34
I found it online, it's made by some french guy, so I cannot ask him.
Well, a lot of french do speak english, so you might try :-)




Or why they do not have specific tutorials for DevC++/VC++ and other specific compilers, with easy to follow steps that once done, everything should work fine without the users having to spend hours and hours reading thru docs trying to figure out how to just compile..
Trolltech has (from what I hear) a rather nice integration to Visual Studio, but it is only included in the commercial package. If those documents do not exist, it would be rather nice if you found the time to write something up and add it to the wiki (http://wiki.qtcentre.org) once your problems are solved. It could save other people a lot of work...the one you are experiencing right now.




I do not use qmake, so I don't know how it is implemented, and I don't understand why it's even there.
QMake is a cross-platform makefile/projectfile generator. I can very easily describe my project, i.e. what sources/headers/resources etc. I am using, and it will generate makefiles or visual studio project files (in the commercial setting or with the hack mentioned a little later) for you. You do not have to care about a thing. Added something? Run QMake again and you are set.




I wish that tutorials were available for QT that wasn't from trolltech, that perhaps had .DEV files or .vc++ files, for VC++ and DevC++. So we do not have to figure this out or use the little qmake stuff. An idea like the template file i showed you, is a great idea, if there was such things for VC++ too that would be great.

Did you check through the Qt Centre Wiki (http://wiki.qtcentre.org/index.php?title=Programming_in_Qt4_and_C%2B%2B)? :-)

Have you tried integration in Visual Studio (http://qtnode.net/wiki/Qt4_with_Visual_Studio)?



Well anyway I guess i'll hope someone who knows how moc should be included in the project when NOT using qmake appears, or someone who uses DevC++ to make QT :D

Good Luck :-)

VireX
14th January 2007, 15:37
I am not gonna ask him. Obviously he made the template and he knew what he was doing, and maybe just didn't think of people that use Q_OBJECT...

It's great that you can describe your project and all. But that means I have to make .pro files and then make shortcuts for qmake and have to change the pro file everytime, to do everything. I'd rather just click Build+run in DevC++ which is much easier. Especially since when making gui I compile and run the program every 10 seconds after every change.

The wiki only mentions DevC++ once, it does mention mingw a lot, but always talks about qmake etc. I guess there has never been a QT programmer that just uses DevC++.

VireX
15th January 2007, 22:21
Sorry I cannot edit anymore.
Anyway, my main questions now is:
1) How do I make simple pro files, and then do : nmake \n qmake? in the folder with the pro file? And this will get rid of this bug?
2) What does qmake do, that my compiler (MingW) with DevC++ does not do?-- What is missing in my project that's not missing when people use qmake? I've tried using "moc.exe" to create a .moc file for my header file in my project. I tried including it in my project, and still same linker errors.

From what I understand, the linker errors are a result of not being able to find the QStaticMetaObject stuff that MOC makes when we macro Q_OBJECT, Because it declares classes and functions to be used, but doesn't implement it. So how can I implement it so that it will stop linker errors? (hopefully without using qmake)

EDIT: ok this time, I just took the whole moc file, and I just pasted it at the bottom of my cpp file : QTmain.cpp I removed the "include QTmain.h" from the moc code.
However, this is still a problem, because that means I have to make an moc file everytime and include that or paste it whatever everytime. Is there an easier way?

jacek
15th January 2007, 23:14
1) How do I make simple pro files, and then do : nmake \n qmake? in the folder with the pro file?

qmake -project
qmake
make
But you should use "qmake -project" only once and later just edit the .pro file manually. Remember to set QT variable in the .pro file, if you use other components than QtCore and QtGui.


2) What does qmake do, that my compiler (MingW) with DevC++ does not do?
It creates a Makefile with proper rules for using moc, rcc and uic.

VireX
16th January 2007, 17:04
Well thx, but it failed.
It kept trying to find mingw-make and stuff, so I put those in system32 (they were in dev-cpp's bin), and then this time after i fixed up the qmake file, and then used mingw32-make, it tried to build it, but it gave hundreds of linker errors "no matching function called operator new(Qstring &......." and things like that. Well i'll keep trying things.

jacek
16th January 2007, 20:46
Well thx, but it failed.
It kept trying to find mingw-make and stuff, so I put those in system32 (they were in dev-cpp's bin), and then this time after i fixed up the qmake file, and then used mingw32-make, it tried to build it, but it gave hundreds of linker errors "no matching function called operator new(Qstring &......." and things like that.
It looks like your compiler isn't installed correctly or at least some environment variables aren't set.

How did you install Qt? Did you use the installer? Did it ask for MinGW location? Also try compiling your application from "Qt 4.2.x Command Prompt".

TheRonin
17th January 2007, 10:36
If you installed Qt and the MinGW compiler correctly, then you should have a PATH variable that points to their respective /bin/ folders. You can check your path by right clicking on My Computer-->properties-->advanced-->environment variables.

The top part of the window that pops up (user variables), should contain a variable called Path. (You may create it if it doesn't already exist). If you double click on it and copy the contents to a text editor so you can get a better overview. If you look at it, you can see if Qt and MinGW's /bin/-paths are included. If not, add them.

My Path-variable looks like this: P:\Qt\MinGW-gcc-3.4.2\bin;P:\Qt\MinGW-gcc-3.4.2\insight\bin;P:\Qt\qt-win-4.1.4-mingw\bin

Once that's done you can call the qmake and make programs from anywhere. I, like Jacek compile like so:

qmake -project (when i'm starting a new project. qmake autogenerates the .pro file.)
qmake (creates the Makefiles from the .pro file.)
make ((or in my case, mingw32-make) compiles the application based on the generated Makefiles.)

When i add new files to my project i add them to the .pro file instead of the Makefile since i run qmake to regenerate the Makefile. Runnin gqmake is not something i need to do every time i compile.

I hope this helps and that you don't write Qt off because of a few stumbles in the beginning. I'm pretty sure the problems you've been experiencing stem from the template file you're using and not Qt itself.

VireX
31st January 2007, 04:41
Using Qt with QTmake is difficult. I used the template file to make it as simple as possible, but that has the setback of the mos handling... so I still havent' found a solution.

But a lot of things turn me off... like just trying to figure out how shortcuts work. Like there is no button->keypressed(QT::ENTER);, which would be the assumed OOP idea... I still haven't figured out how to get those kinds of events... i'll keep searching tho...
EDIT: hah thats hilarious, i just found button->setAccel, didnt see it before. scratch that! But I still dont know how to set a shortcut just by pressing the KEY, like how F1 will bring help in most programs.

THe fact alone that I haven't found a single major tutorial site with lots of Qt tutorials. The only resources is, Qt's own docs and this forum... I haven't found any site, that walks thru programming something as simple as an instant messenger, or a notepad with a lot of functions. I know there is like a syntax highlighter example somewhere around here, but i mean i haven't seen others elsewhere.

TheRonin
31st January 2007, 09:18
Well, i'm sorry you find working with qmake difficult. Since it's only a few steps to use it the first time, most of us don't need a template file since using one would in all likelihood add more steps than it removed. I had hoped that my last post would clear things up for you a little but i guess it didn't :( I'll have to work on explaining things more clearly in the future.

The specific problem you mention can be solved with a look at some of the Qt examples included in your installation or a search through the forums. I don't have the answer for you on hand but i recall seeing some example of how to do it. If i'm not mistaken you will need to register to receive keyPressed events from your main widget and then implement a protected method for it. In that method you can filter for the desired key(s). I did something like that in an application that was to have a unique responce to the enter key. I'm sorry i can't give you more elaborate help than that right now but i don't have access to my Qt stuff at the moment.

When i work with Qt and try to do something new, i often turn to these forums and the Qt Assistant (that is to say, the Qt api and documentation). 99% of the time i can find an example or a thorough explanation of the steps involved in using some feature or performing a task. Sure, it's a little work, but i personally find the detective work involved in figuring out how to do something to be part of the thrill. Makes seeing it work that much more enjoyable. At the same time i can understand your frustration. Perhaps there should be some site dedicated to open-source Qt projects where more elaborate examples could be made available.

best of luck.
-TR