custom slots / generated ui
Hi all
I have created a Qt application using MSVS 2010 with the Qt Add-In. I created the UI in designer and added two new slots for the QMainWindow (called generat0rXClass in my case). I have created two actions (exit_slot(), addScene2D_slot() ) which trigger the slots. Designer has generated the following code:
Code:
QObject::connect(actionExit,
SIGNAL(activated
()), generat0rXClass,
SLOT(exit_slot
()));
QObject::connect(actionNew_2D_Scene,
SIGNAL(activated
()), generat0rXClass,
SLOT(addScene2D_slot
()));
In my main class (generated by the add-In as well, called "generat0rX"
like so:
Code:
void exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
}
But nothing happens (the click on the corresponding ui element does not trigger the slot). Why is that?
Cheers,
Michael
Re: custom slots / generated ui
Sniffed around in the logs a bit and found the following errors:
Code:
Object::connect: No such slot generat0rX::exit_slot() in E:\workspace\QTProjects\generat0rX\generat0rX\GeneratedFiles\ui_generat0rx.h:421
Object::connect: (sender name: 'actionExit')
Object::connect: (receiver name: 'generat0rXClass')
Object::connect: No such slot generat0rX::addScene2D_slot() in E:\workspace\QTProjects\generat0rX\generat0rX\GeneratedFiles\ui_generat0rx.h:422
Object::connect: (sender name: 'actionNew_2D_Scene')
Object::connect: (receiver name: 'generat0rXClass')
Im a bit lost on this one - seems to be a namespace problem with the code (generated by the Add-In)
Anyone?
Re: custom slots / generated ui
Where is the class definition for exit_slot() ?
Re: custom slots / generated ui
in the generat0rx.h file:
Code:
#ifndef GENERAT0RX_H
#define GENERAT0RX_H
#include <QtGui/QMainWindow>
#include "ui_generat0rx.h"
{
Q_OBJECT
public:
generat0rX
(QWidget *parent
= 0, Qt
::WFlags flags
= 0);
~generat0rX();
void exit_slot();
private:
Ui::generat0rXClass ui;
};
#endif // GENERAT0RX_H
Re: custom slots / generated ui
There's no slots defined in that header file. You need at least something like "public slots:" for example to show which functions are slots.
Secondly, this:
Code:
void exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
}
Isn't valid C++. This a C function.
Re: custom slots / generated ui
Using the Designer, I was not really sure what needs to be done where.
So when I try to add the "public slots:" in "generat0rX.h", I get a linker error that states something around
Code:
"symbol not found in ui_generat0rX.h"
(I am not at my workstation, can post the exact linker error later). When I remove the "public slots:" statements, the code compiles again.
I have created the two additional slots also in Designer (as part of generat0rXClass) by right-clicking on generat0rXClass and editing "Signals/Slots".
On the "isn't valid c++": What is wrong with it? (btw: I copy/pasted it from a Nokia Qt tutorial ;) )
Re: custom slots / generated ui
Once you have added slots to a header file, you must invoke the MOC to generate the appropriate dependancies. This is typically done by updating the project (In QtCreator I think is called "run qmake" or similar).
Please post a link to the Nokia Qt tutorial.
Re: custom slots / generated ui
I changed generat0rx.h to this:
Code:
#ifndef GENERAT0RX_H
#define GENERAT0RX_H
#include <QtGui/QMainWindow>
#include "ui_generat0rx.h"
{
Q_OBJECT
public:
generat0rX
(QWidget *parent
= 0, Qt
::WFlags flags
= 0);
~generat0rX();
//void exit_slot();
//void addScene2D_slot();
public slots:
void exit_slot(void);
void addScene2D_slot(void);
private:
Ui::generat0rXClass ui;
};
#endif // GENERAT0RX_H
which, when compiling gives me this output:
Code:
1>------ Build started: Project: generat0rX, Configuration: Debug Win32 ------
1> Moc'ing include\generat0rx.h...
1> moc_generat0rx.cpp
1> generat0rx.cpp
1> main.cpp
1> Generating Code...
1>moc_generat0rx.obj : error LNK2019: unresolved external symbol "public: void __thiscall generat0rX::addScene2D_slot(void)" (?addScene2D_slot@generat0rX@@QAEXXZ) referenced in function "public: virtual int __thiscall generat0rX::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@generat0rX@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
1>moc_generat0rx.obj : error LNK2019: unresolved external symbol "public: void __thiscall generat0rX::exit_slot(void)" (?exit_slot@generat0rX@@QAEXXZ) referenced in function "public: virtual int __thiscall generat0rX::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@generat0rX@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
1>E:\workspace\QTProjects\generat0rX\\generat0rX.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I pasted the full output so you see what the compiler (MSVS / QT Add-In in my case) does. It says that it does moc things as far as I can tell.
Here is the link to the sample: http://doc.trolltech.com/4.7/qmessagebox.html
Re: custom slots / generated ui
Did have any CPP file with methods void generat0rX::exit_slot(void) and void generat0rX::addScene2D_slot(void) definitions ?
Re: custom slots / generated ui
By "not valid C++", I mean this:
Code:
void exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
}
to this:
Code:
void generat0rX::exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
}
Re: custom slots / generated ui
@Lesiok:
Yes, the methods are defined here:
Code:
#include "generat0rx.h"
#include "qmessagebox.h"
{
ui.setupUi(this);
}
generat0rX::~generat0rX()
{
}
void generat0rX::exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
//qApp->quit();
//qApp->exit();
}
void generat0rX::addScene2D_slot()
{
msgBox.setText("SLOT: addScene2D triggered");
msgBox.exec();
}
Any idea whats wrong?
Re: custom slots / generated ui
Quote:
Originally Posted by
mboeni
...
[/CODE]
But nothing happens (the click on the corresponding ui element does not trigger the slot). Why is that?
...
What ui element should trigger the action?
Did you connect the action to that element?
How did you do that?
Note that a slot can also be called without the use of a QAction. So, when you use a QPushButton, you can connect directly to the clicked() signal. No QAction involved.
Re: custom slots / generated ui
@boudie: Here is what I did:
1. I created a project in MSVS 2010 using the Add-In
2. In Designer, I created my UI
3. I created two actions: "actionExit" and "actionNew_2D_Scene" in the action editor
4. I drag/dropped the two actions to a menubar and to a toolbar
5. Then I added two custom slots (in the designer), named "exit_slot()" and "addScene2D_slot()" to "generat0rXClass" which is my QMainWindow
6. Then I created two connections in the designer, which shows like follows in "ui_generat0rx.h":
Code:
QObject::connect(actionExit,
SIGNAL(activated
()), generat0rXClass,
SLOT(exit_slot
()));
QObject::connect(actionNew_2D_Scene,
SIGNAL(activated
()), generat0rXClass,
SLOT(addScene2D_slot
()));
I assumed that this should work - but I keep getting this error
Code:
Object::connect: No such slot generat0rX::exit_slot() in E:\workspace\QTProjects\generat0rX\generat0rX\GeneratedFiles\ui_generat0rx.h:532
Object::connect: (sender name: 'actionExit')
Object::connect: (receiver name: 'generat0rXClass')
Please note: If I use a standard slot like "close()" of generat0rXClass - it works!
So i must be missing something somewhere :s
Re: custom slots / generated ui
Ok, I tried it the manual way also: I removed the two custom slots and the connection in designer and did it in code. My class now looks like this:
generat0rx.h
Code:
#ifndef GENERAT0RX_H
#define GENERAT0RX_H
#include <QtGui/QMainWindow>
#include "ui_generat0rx.h"
class generat0rX
: public QMainWindow,
private Ui
::generat0rXClass{
Q_OBJECT
public:
generat0rX
(QWidget *parent
= 0, Qt
::WFlags flags
= 0);
~generat0rX();
public slots:
void exit_slot(void);
void addScene2D_slot(void);
private:
Ui::generat0rXClass ui;
};
#endif // GENERAT0RX_H
and generat0rx.cpp
Code:
#include "generat0rx.h"
#include "qmessagebox.h"
{
ui.setupUi(this);
QObject::connect(actionExit,
SIGNAL(activated
()),
this,
SLOT(exit_slot
()));
QObject::connect(actionNew_2D_Scene,
SIGNAL(activated
()),
this,
SLOT(addScene2D_slot
()));
}
generat0rX::~generat0rX()
{
}
void generat0rX::exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
//qApp->quit();
//qApp->exit();
}
void generat0rX::addScene2D_slot()
{
msgBox.setText("SLOT: addScene2D triggered");
msgBox.exec();
}
Now the above error is gone but I get a runtime exception:
Code:
> QtCored4.
dll!QObject::connect(const QObject * sender
=0x00690000,
const char * signal=0x00c5d294,
const QObject * receiver
=0x0026f5c0,
const char * method
=0x00c5d270, Qt
::ConnectionType type
=AutoConnection
) Line
2483 + 0x8 bytes C
++ generat0rX.
exe!generat0rX
::generat0rX(QWidget * parent
=0x00000000, QFlags<enum Qt
::WindowType> flags
={...
}) Line
8 + 0x31 bytes C
++ generat0rX.exe!main(int argc=1, char * * argv=0x0069f9f0) Line 24 + 0x1d bytes C++
generat0rX.exe!WinMain(HINSTANCE__ * instance=0x00980000, HINSTANCE__ * prevInstance=0x00000000, char * __formal=0x00072b9a, int cmdShow=1) Line 131 + 0x12 bytes C++
generat0rX.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
generat0rX.exe!WinMainCRTStartup() Line 371 C
and the debugger points to this line in "qobject.cpp":
Any ideas?
Re: custom slots / generated ui
Your toolbar probably contains one or more QToolButtons. When such button is clicked, the clicked signal for that button is emitted. To react to the signal, you must have in the constructor of your class something like this:
Code:
connect(myButton, SIGNAL(clicked()), this, SLOT(mySlot()));
Then every time the button is clicked, the code in function mySlot() is executed.
In your GeneratorClass.h you have something like:
Code:
private slots:
void mySlot();
And.. please read the Qt-docs about signals and slots. It really helps...
Re: custom slots / generated ui
Try the signal "triggered()" of your actions instead of "activated()":
#
QObject::connect(actionExit, SIGNAL(triggered()), this, SLOT(exit_slot()));
#
QObject::connect(actionNew_2D_Scene, SIGNAL(triggered()), this, SLOT(addScene2D_slot()));
Re: custom slots / generated ui
Hi all
First of all, thanks for the input! Alas, none of it worked.
I tried something very simple and get exceptions too. So I assume the problem is rooted deeper. I have added a simple widget manipulation to generat0rx.cpp:
Code:
#include "generat0rx.h"
#include "qmessagebox.h"
#include <QxtLogger>
#include <QxtBasicFileLoggerEngine>
{
ui.setupUi(this);
//QObject::connect(actionExit, SIGNAL(activated()), this, SLOT(exit_slot()));
//QObject::connect(actionNew_2D_Scene, SIGNAL(activated()), this, SLOT(addScene2D_slot()));
//Start logging
qxtLog->addLoggerEngine("FileLogger", new QxtBasicFileLoggerEngine("log/g0x.log"));
qxtLog->info("Huhu INFO log entry!");
outputTabTextEdit->append("TEST");
}
generat0rX::~generat0rX()
{
}
void generat0rX::exit_slot()
{
msgBox.setText("SLOT: exit_slot triggered");
msgBox.exec();
//qApp->quit();
//qApp->exit();
}
void generat0rX::addScene2D_slot()
{
msgBox.setText("SLOT: addScene2D triggered");
msgBox.exec();
}
This line was added in the constructor:
Code:
outputTabTextEdit->append("TEST");
and even THIS raises an exception. There must be something fundamentally wrong with the way I call ui elements...(I am using multiple inheritance btw). Just to make sure you get the full picture, here is generat0rx.h as well:
Code:
#ifndef GENERAT0RX_H
#define GENERAT0RX_H
#include <QtGui/QMainWindow>
#include "ui_generat0rx.h"
class generat0rX
: public QMainWindow,
private Ui
::generat0rXClass{
Q_OBJECT
public:
generat0rX
(QWidget *parent
= 0, Qt
::WFlags flags
= 0);
~generat0rX();
public slots:
void exit_slot(void);
void addScene2D_slot(void);
private:
Ui::generat0rXClass ui;
};
#endif // GENERAT0RX_H
This is getting really frustrating :s
Here is the call stack:
Code:
> QtGuid4.
dll!QTextEdit::append(const QString & text
="TEST") Line
2617 + 0x7 bytes C
++ generat0rX.
exe!generat0rX
::generat0rX(QWidget * parent
=0x00000000, QFlags<enum Qt
::WindowType> flags
={...
}) Line
17 + 0x2e bytes C
++ generat0rX.exe!main(int argc=1, char * * argv=0x0079fab0) Line 17 + 0x1d bytes C++
generat0rX.exe!WinMain(HINSTANCE__ * instance=0x01040000, HINSTANCE__ * prevInstance=0x00000000, char * __formal=0x000a2b9a, int cmdShow=1) Line 131 + 0x12 bytes C++
generat0rX.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
generat0rX.exe!WinMainCRTStartup() Line 371 C
kernel32.dll!76e31194()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!775eb495()
ntdll.dll!775eb468()
Re: custom slots / generated ui
You are mixing the different approaches of using ui files: See "Using a Designer UI File in Your Application" at the docs.
Use instead of and rerun qmake.
Re: custom slots / generated ui
Hi Lykurg
I have read the article you mentioned, but missed the part about setupUI. Changing that as you proposed has solved my main issues. Thanks!
Cheers,
Michael
Re: custom slots / generated ui
For all other newbies out there, I have put together a little tutorial on how to master the first few steps with Qt4 and MS Visual Studio using the Add-In.
You find the tutorial here: Beginners Tutorial Qt 4.7 with Visual Studio and the Qt Add-In
Please comment or PM me in the blog if you find any errors.
All the best,
Michael