I'm trying to call my function as a function slot in Qt,But i don't know how to go about it.
it seems the following approach is wrong :
Update:
According to an answer i updated my source code,but still something is apparently wrong with it.Trying to compile this snippet of code causes these errors:
C2515:' no appropriate default constructor is available.'
And
C2665: QObject::connect':none of the 3 overloads could convert all the
arguments.'
respectively in Visual studio 2010.
#include <QtGui/QApplication>
#include <QPushButton>
#include <QObject>
#include <QMessageBox>
class myclass;
int main(int argc,char *argv[])
{
QApplication a(argc,argv);
QPushButton btnshowmessage("show");
myclass *my=new myclass();
QObject::connect(&btnshowmessage,SIGNAL(clicked()),my,SLOT(warningmessage()));
btnshowmessage.show();
return a.exec();
}
//////////////////////////////////////////////////////////////////////////
class myclass: public QObject
{
Q_OBJECT
public:myclass(){}
public slots:
void warningmessage()
{
QMessageBox::warning(0,"Warning","Test Message!",QMessageBox::Ok);
}
};
You use signals and slots to connect one Object's signal to another Object's slot. Every signal or slot should be inside a class which must be also derived from QObject class and contain the Q_OBJECT macro.
So to make your code work, put the slot into some class of yours:
class MySlotClass:public QObject
{
Q_OBJECT
public slots:
void MyFunction()
{
QMessageBox::warning(0,"WarningTest","This is a waring text message",QMessageBox::Ok);
}
}
and connect like this:
MySlotClass m = new MySlotClass();
Qobject::connect(&btnShowaMessageBox,SIGNAL(clicked()), &m ,SLOT(MyFunction()));
Currently Qt does not allow connection of signals to functions that are not declared as slots on some QObject derivative. I believe Qt5 may offer this possibility, but connect will have different syntax to allow this.
basically your slot function must be in a QObject derived class and declared in a
public slots:
section.
Read the documentation on signals/slots.
Related
I'm having trouble moving from VC++ to Qt-style programming with slots/signals. I wanted to create a button with an image that, when clicked, changed to another image, and when released, changed back to its original. I created a class called ClickableQLabel that inherits from QLabel, but it's telling me that certain functions are re-defined. Specifically, the ones that are emitted.
MainProgram.cpp
#include "MainProgram.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
CodeVault w;
w.show();
return a.exec();
}
MainProgram.h
#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H
#include <QMainWindow>
#include "clickableqlabel.h"
namespace Ui {
class MainProgram;
}
class MainProgram : public QMainWindow
{
Q_OBJECT
public:
explicit MainProgram(QWidget *parent = 0);
~MainProgram();
private:
Ui::MainProgram *ui;
};
#endif // MAINPROGRAM_H
clickableqlabel.h
#ifndef CLICKABLEQLABEL_H
#define CLICKABLEQLABEL_H
#include <QLabel>
#include <QMouseEvent>
using namespace Qt;
class ClickableQLabel : public QLabel {
Q_OBJECT
QPixmap pushed;
QPixmap unpushed;
public:
ClickableQLabel(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *eve );
void mouseReleaseEvent(QMouseEvent *eve );
void setPushed(QPixmap &p);
void setUnpushed(QPixmap &p);
signals:
void leftButtonPressed(ClickableQLabel* sender);
void leftButtonReleased(ClickableQLabel* sender);
};
#endif // CLICKABLEQLABEL_H
clickableqlabel.cpp
#include "clickableqlabel.h"
ClickableQLabel::ClickableQLabel(QWidget *parent) : QLabel(parent){
// set up qlabel
}
void ClickableQLabel::setPushed(QPixmap &p){
pushed = p;
}
void ClickableQLabel::setUnpushed(QPixmap &p){
unpushed = p;
}
void ClickableQLabel::leftButtonPressed(ClickableQLabel* sender){
if(!pushed.isNull())
sender->setPixmap(pushed.scaledToWidth(sender->width()));
}
void ClickableQLabel::leftButtonReleased(ClickableQLabel* sender){
if(!unpushed.isNull())
sender->setPixmap(unpushed.scaledToWidth(sender->width()));
}
void ClickableQLabel::mousePressEvent(QMouseEvent *eve ){
if(eve->button() == Qt::LeftButton){
emit leftButtonPressed(this);
}
}
void ClickableQLabel::mouseReleaseEvent(QMouseEvent *eve ){
if(eve->button() == Qt::LeftButton){
emit leftButtonReleased(this);
}
}
What I receive is the following 3 errors:
moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonPressed(class ClickableQLabel *)" (?leftButtonPressed#ClickableQLabel##QEAAXPEAV1##Z) already defined in clickableqlabel.obj
moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonReleased(class ClickableQLabel *)" (?leftButtonReleased#ClickableQLabel##QEAAXPEAV1##Z) already defined in clickableqlabel.obj
debug\CodeVault.exe:-1: error: LNK1169: one or more multiply defined symbols found
The two functions that are causing the errors are the two signals in the clickableqlabel.h file. How am I supposed to set up the connect function and where?
You shouldn't provide an implementation for your signals. You just declare signals in the class header. the Qt moc provides an implementation that is responsible to call the slots connected to the signal when it is emitted, see this. Because you are providing an implementation and Qt moc is providing another one, you end up with two different implementations and the linker complains.
so, to make some piece of code execute when a signal is emitted, you can put it in some slot that is connected to that signal, or you can execute it manually before emitting the signal. . .
Another thing to note is that your signals have a parameter named sender. normally there is no need to do this, QObject::sender() provides similar functionality.
How am I supposed to set up the connect function and where?
When you instantiate your ClickableQLabel in your MainProgram window for example (You can do this by using ClickableQLabel in a .ui form file), you can connect its signals to slots of the MainProgram, like this.
mainprogram.h
#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H
#include <QMainWindow>
#include "clickableqlabel.h"
namespace Ui {
class MainProgram;
}
class MainProgram : public QMainWindow
{
Q_OBJECT
public:
explicit MainProgram(QWidget *parent = 0);
~MainProgram();
public slots:
void labelPressed();
void labelReleased();
private:
Ui::MainProgram *ui;
};
#endif // MAINPROGRAM_H
then in the constructor connect the ClickableQLabel's signals to the MainProgram's slots , something like this:
connect(clickableLabel, SIGNAL(leftButtonPressed()), this, SLOT(labelPressed()));
where clickableLabel is your ClickableQLabel object.
You should not explicitly define signal "functions" - they are simply emitted (as you do in the mousePressEvent() and mouseReleaseEvent() functions).
If you want some action performed (such as setPixmap), you would either do that in the slot functions that are connected to those signals, or perhaps directly in the mousePressEvent and mouseReleaseEvent functions.
Unrelated, but you may also need to do something like qRegisterMetaType<ClickableQLabel>() to use that data type with the signal/slot mechanism.
You don't need to subclass QLabel to achieve this: put an onLabelButtonClicked slot (method) in your MainWindow class, which is connected to the QPushButton clicked() signal, and which calls setText / setIcon as required.
If you want to re-use this clickable element you can of course encapsulate it in a class, but subclassing and handling raw-events is only required in Qt when defining new kinds of widget; if you're simply composing standard functionality (being clicked, adjusting appearance) then slots on your main window / dialog class are usually sufficient.
I am trying to run QTimer and have it warn me when timeouting. To do so, I use slot and signal to link the two.
The guy.h:
#ifndef GUY_H
#define GUY_H
#include <QGraphicsItem>
#include <QTimer>
#include <QObject>
class Guy : public QGraphicsItem
{
public:
Guy(int x, int y);
void timerStart();
public slots:
void onTimeOutTimer();
[...]
QTimer *timer;
}
#endif // GUY_H
The guy.cpp:
#include "guy.h"
#include <QTimer>
#include <QObject>
#include <stdio.h>
#include <iostream>
Guy::Guy(int x, int y)
{
timer = new QTimer();
}
void Guy::timerStart()
{
QObject::connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOutTimer()));
this->timer->setInterval(1000);
this->timer->start();
std::cout << "starting timer" << std::endl;
}
void Guy::onTimeOutTimer()
{
std::cout << "check" << std::endl;
}
But as an ouput, I get this error:
No matching function for call to 'QObject::connect(QTimer*&, const char*, Guy* const, const char*)'
As I undertsand it is that QTimer is no QObject required as first input of the function connect(), but the documentation specifies QTimer inherits from QObject.
I have no clue here.
You will need to inherit from QObject, too, to get this working as signals and slots are availabl for QObjects. QGraphicsItem does not inherit QObject, not even indirectly.
Not only that, you will also need to add the Q_OBJECT macro as follows:
class Guy : public QObject, public QGraphicsItem
{
Q_OBJECT
...
}
or even better because QGraphicsObject inherits QObject and QGraphicsItem.
...
#include <QGraphicsObject>
...
class Guy : public QGraphicsQObject
{
Q_OBJECT
...
}
Also, if you make this change, I suggest to change the QObject::connect to connect as you do not need to indicate the QObject:: scope then.
On a side note, including stdio.h does not seem to make sense here.
Furthermore, allocating the QTimer instance on the heap looks like wasteful to me. It is not only leaking the memory, but also adds additional complexity. Even if you allocate it on the heap, you should pass this as the parent and use the initializer list or C++11 style initialization. Also, if you allocate it on the heap, you could use forward declaration in the header.
If the slot is not used outside the class, you should also make that private.
It is probably also a bad idea to make the timer member public. Hopefully you do not do that.
You can inherit from QGraphicsObject which provides a base class for all graphics items that require signals, slots and inherits QGraphicsItem and QObject. Also add Q_OBJECT macro in your class declaration.
If you use new Qt5 style connects as in
QObject::connect(timer, &QTimer::timeout, this, &Guy::onTimeOutTimer)
The onTimeOutTimer function does not need to be marked as slot, and Guy could stay a non-QObject. Much slimmer and less macros involved.
I'm writing a program that send an UDP frame every 10 mS. Here's how my program is supposed to work :
I've got a client class :
//Constructor
clientSupervision::clientSupervision()
{
}
void clientSupervision::sendDataUDP(){
//Create a frame and send it
...
}
void clientSupervision::sendDataUDPTimer(int timer){
QTimer *tempsEnvoieTrameSupervision = new QTimer();//Create a timer
tempsEnvoieTrameSupervision->setInterval(timer);//Set the interval
//Mise en place des connections
QObject::connect (tempsEnvoieTrameSupervision,SIGNAL (timeout()),this, SLOT (envoiTrameSupervision())); //Connect the timer to the function
tempsEnvoieTrameSupervision->start();// Start the timer
}
//Call sendDataUDP
void clientSupervision::envoiTrameSupervision(){
std::cout << "Envoi de la trame de supervision";
sendDataUDP();
}
My header file of clienSupervision.h :
#ifndef CLIENTSUPERVISION_H
#define CLIENTSUPERVISION_H
#include <winsock2.h> // pour les fonctions socket
#include <cstdio> // Pour les Sprintf
#include "StructureSupervision.h"
#include "utilitaireudp.h"
#include <QTimer>
#include <QObject>
#include <iostream>
class clientSupervision
{
Q_OBJECT
public:
clientSupervision();
void sendDataUDP();
void sendDataUDPTimer(int timer);
public slots:
void envoiTrameSupervision();
};
#endif // CLIENTSUPERVISION_H
Then I use this in my main :
int main(int argc, char *argv[])
{
clientSupervision c;
c.sendDataUDPTimer(10);
QCoreApplication a(argc, argv);
return a.exec();
}
I've got the error :
no matching function for call to 'QObject::connect(QTimer*&, const char*, clientSupervision* const, const char*)
I don't understand why the connect function can't find a matching function.
What should I change?
There can be several reasons for the issue in general:
You do not inherit QObject.
You do not have the Q_OBJECT macro in your class.
You do not define the method as slot in your header file where the class is declared.
Your issue is the first which can be seen here:
class clientSupervision
You should change your code to:
class clientSupervision : public QObject
// ^^^^^^^^^^^^^^^^
Of course, the constructor implementation and signature would need to change, too, as follows:
explicit clientSupervision(QObject *parent = Q_NULL_PTR) : QObject(parent) { ... }
In addition, you seem to leak your QTimer instance as it does not get the parent as a parameter to the constructor.
Furthermore, the QObject:: scope is needless in your code as your class ought to inherit QObject directly or indirectly either way.
Even more, I would highly encourage you to utilize the new signal-slot syntax.
Another possible cause of this error is trying to connect to a slot which is overloaded. For example, this well cause the same error
QObject::connect(this,
&MazeWidget::MyUpdate,
this,
&QWidget::update,
Qt::QueuedConnection);
But not if you explicitely cast:
QObject::connect(this,
&MazeWidget::MyUpdate,
this,
static_cast<void (QWidget::*)()>(&QWidget::update),
Qt::QueuedConnection);
Here's another one that snuck up on me: The class of the slot object had been forward declared in the header, but not defined in the implementation by including its header.
If none of the answers above worked, check if you have assigned correct object to the signals and the slots. You will get this error when the signals and slots are valid and refer to one object but the object assigned to that signal and slot is different.
I am trying to subclass QEditLine so that I can define a new SIGNAL that sends an object identifier. At the moment, I connect a parent signal to a slot in the new class and from that slot I emits a proper new signal with the additional object identifier.
I cannot understand one thing. The problem is I don't know how to define a new signal function itself. I don't know what I should put there. I mean I know its arguments but I don't know what it shpould do as a function. I am doing this for the first time and it may looks very silly ;p but I really stuck there >.<.
Can anybody please provide some clues. It is probably a very easy problem.
Thanks
// myqeditline.h
#ifndef MYQEDITLINE_H
#define MYQEDITLINE_H
#include <QWidget>
#include <QLineEdit>
#include <QString>
class MyQEditLine : public QLineEdit
{
Q_OBJECT
public:
explicit MyQEditLine(const QString& n, QWidget *parent = 0);
protected:
QString name;
signals:
void textChanged(QString textCHanged, QString sender);
protected slots:
public slots:
void myTextChanged(QString textChanged);
};
#endif // MYQEDITLINE_H
// myqeditline.cpp
#include "myqeditline.h"
MyQEditLine::MyQEditLine(const QString &n, QWidget *parent)
: QLineEdit(parent),name(n) {
connect(this,SIGNAL(textChanged(QString)),this,SLOT(myTextChanged(QString)));
}
void MyQEditLine::myTextChanged(QString textChanged) {
emit textChanged(QString textChanged, QString name);
}
I just realised that the answer to my question is on this Qt Project website, in section regarding "Signals", in 4th paragraph. It says: "Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void)."
I am fairly new to Qt. I have done some simple modifications to an existing Qt application, but I haven't created any from scratch yet.
I also don't have really much experience with certain aspects of C++ in general (class inheritance etc).
I have created a new Code::Blocks Qt4-based project and modified the template a bit. I have added two files.
Right now the project contains three files: main.cpp, app.h and app.cpp.
This is the content of main.cpp:
#include <QTimer>
#include "app.h"
int main(int argc, char* argv[]) {
TestApp app(argc, argv);
QTimer::singleShot(1000, &app, SLOT(timeout()));
return app.exec();
}
This is what app.h looks like:
#ifndef APP_H_INCLUDED
#define APP_H_INCLUDED
#include <QApplication>
class TestApp: public QApplication {
public:
TestApp(int &argc, char **argv);
public slots:
void timeout();
};
#endif
And this is app.cpp:
#include "app.h"
#include <QDebug>
TestApp::TestApp(int &argc, char **argv): QApplication(argc, argv) {
}
void TestApp::timeout() {
qDebug() << "timeout called";
}
I expected the program to print "timeout called" one second after startup. Unfortunately, this doesn't work. When QTimer::singleShot() is called, the console says:
Object::connect: No such slot QApplication::timeout() in [path to the main.cpp file]
Object::connect: (receiver name: 'QtTests')
I have no idea how to deal with this. Thank you in advance.
You're simply missing the Q_OBJECT macro in your TestApp class:
class TestApp: public QApplication {
Q_OBJECT
public:
...
This is necessary for the whole signal/slot infrastructure to work (and deriving from a class that has this macro is not sufficient).
(Make sure you do a full, clean build after that change - and if you don't use qmake or some other Qt-aware build system, you'll need to run moc yourself.)
For reference, see the QObject docs:
Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the Meta Object Compiler on the source file. We strongly recommend the use of this macro in all subclasses of QObject regardless of whether or not they actually use signals, slots and properties, since failure to do so may lead certain functions to exhibit strange behavior.
You need to create a moc file, which is created with qmake if you put Q_OBJECT macro in your class.
So, to fix your example, you need your class changed to this :
class TestApp: public QApplication {
Q_OBJECT
public:
TestApp(int &argc, char **argv);
public slots:
void timeout();
};