I have a function which I am trying to connect via signals and slots but the function isn't being called when I run the executable file. I have put a debug error in my function so I know it isn't being called. My code is shown below:
My header file:
#include "MyWidget.h"
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass: public QObject{
Q_OBJECT
public:
MyClass( QObject *parent = nullptr);
MyWidget *myWidget;
public slots:
void setTranslation(int value);
};
#endif
My source file:
#include "MyClass.h"
MyClass::MyClass(QObject *parent): QObject(parent)
{
some code here....
QSlider *xSlider = new QSlider(Qt::Vertical);
xSlider->setRange(0, 10);
QObject::connect(xSlider, SIGNAL(valueChanged(int)),
this, SLOT(setTranslation(int)));
some code here...
}
void MyClass::setTranslation(int value)
{
some code here...
}
You forgot to add the Q_OBJECT macro immediately after the class declaration. It is what the MOC (Meta Object Compiler) uses to generate additional meta information for your code.
class MyClass: public QObject
{
Q_OBJECT
// all other class data, member function declaration
public:
MyClass( QObject *parent = nullptr );
};
This should be good enough.
EDIT:
Also remember to take a nullptr defaulted QObject pointer in your default constructor.
Related
this is the problem given to me
create a project called datamanager and its base class should be QWidget
add a new class called controller inherited from QObject
and 2 slots called sensordatarecived and startdatacollection in controller
add another class called commonreader class inherited from QObject
define 2 signals called readingStarted() and readCompleted() in commonreader class
add a slot called sendData()
declare a virtual function called monitor() in the commonreader class
add 5 new sensor classes which inherit from the commonreader class
in all of the above classes reimplement the common Monitor() function
using QTimer object implement emit readingStarted() from the monitor() function of each of the 5 classes defined
implement the sendData() slot
emit signal called readcompleted inside the send dataslot()
create the object of each of the above sensor classes in the constructor of the controller
call monitor() function of the method sensor objectfrom startDataCollection()
connect readComplete() signal of each object to sensordatarecieved() of the controller.
these are the steps i have to follow for a project.i am stuck in the 14 th step and i need help.
//controller.h
class controler : public QObject
{
Q_OBJECT
public:
explicit controler(QObject *parent = nullptr);
signals:
public slots:
void sensorDataRecived();
void startDataCollection();
};
//controller.cpp
#include "controler.h"
#include <QDebug>
#include "heart_1_sensor.h"
#include "eye_2_sensor.h"
#include "brain_3_sensor.h"
#include "ear_5_sensor.h"
#include "head_4_sensor.h"
#include "commonreaderclass.h"
controler::controler(QObject *parent) : QObject(parent)
{
commonReaderClass *h1=new heart_1_Sensor;
commonReaderClass *e2=new eye_2_Sensor;
commonReaderClass *b3=new brain_3_sensor;
commonReaderClass *e5=new ear_5_sensor;
commonReaderClass *h4=new head_4_sensor;
}
void controler::sensorDataRecived()
{
qDebug()<<Q_FUNC_INFO<<endl;
}
void controler::startDataCollection()
{
}
//commonreaderclass.h
#ifndef COMMONREADERCLASS_H
#define COMMONREADERCLASS_H
#include <QObject>
class commonReaderClass : public QObject
{
Q_OBJECT
public:
explicit commonReaderClass(QObject *parent = nullptr);
virtual void monitor();
signals:
void readingStarted();
void readCompleted();
public slots:
void sendData();
};
#endif // COMMONREADERCLASS_H
//commonreaderclass.cpp
#include "commonreaderclass.h"
#include <QDebug>
#include <QTimer>
commonReaderClass::commonReaderClass(QObject *parent) : QObject(parent)
{
}
void commonReaderClass::sendData()
{
qDebug()<<"sending data has started"<<endl;
emit readCompleted();
}
//sensor1.h
#ifndef HEART_1_SENSOR_H
#define HEART_1_SENSOR_H
#include "commonreaderclass.h"
class heart_1_Sensor:public commonReaderClass
{
public:
heart_1_Sensor();
virtual void monitor();
};
#endif // HEART_1_SENSOR_H
//sensor 1.cpp
#include "heart_1_sensor.h"
#include <QDebug>
#include <QTimer>
heart_1_Sensor::heart_1_Sensor()
{
}
void heart_1_Sensor::monitor()
{
qDebug()<<"monitoring the heart"<<endl;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
timer->start(2000);
emit readingStarted();
}
//and another 4 sensors of the same implementation
I agree with #molbdnilo that you should make h1, e2, ... members of the class, instead of local variables in the constructor. But in this case, there is one more consideration: the lifetime of QObject instances is special, because the parent/children relationship between them so the children can be automatically destroyed when the parent is destroyed. I recommend you this book (paper printed versions also available). Specially chapter 2 about classes and chapter 8 about QObject and other important Qt classes. This book is a curriculum, you should follow it from start to end, and also read other books.
controller.h
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
~Controller(); // the destructor
// ... more public members
signals:
// ...
public slots:
// ...
private:
commonReaderClass *m_h1;
commonReaderClass *m_e2;
// ...
};
I've renamed variables h1 to m_h1 and e2 to m_e2, following a common convention for member variable names, and the Controller class name starting with uppercase is another common naming convention.
controller.cpp (the classic C++ way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor;
m_e2 = new eye_2_Sensor;
// ...
}
Controller::~Controller()
{
delete m_h1;
delete m_e2;
// ...
}
controller.cpp (the Qt way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor(this);
m_e2 = new eye_2_Sensor(this);
// ...
}
Controller::~Controller()
{ }
The second version of controller.cpp is generally preferred when writing Qt based programs. You should remember that in C++ every pointer initialized with a new operation should have a corresponding delete operation. There is not automatic "garbage collection" in C++, but QObject provides a fairly comfortable mechanism to automatically delete children objects, so the destructor in this second version may be empty or you can omit entirely.
In the main.cppi'm creating a singleton type of a class to use it in qml with the following function:
qmlRegisterSingletonType<DataloopWrapper>("com.xpto.connector", 1, 0, "DataloopWrapper",&DataloopWrapper::qmlInstance);
a bit down on the main.cpp i call a function of another object where i want to call a function from that singleton
maybe something like this qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance); is possible?
I'm declaring QmlTranslatorclass the following way:
#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H
#include <QObject>
#include <QTranslator>
#include <QQmlEngine>
#include <QGuiApplication>
class QmlTranslator : public QObject
{
Q_OBJECT
public:
QmlTranslator(QQmlEngine *engine, QGuiApplication *app);
Q_INVOKABLE void selectLanguage(QString language);
void InstallTranslator();
void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);
virtual ~QmlTranslator();
signals:
void languageChanged();
private:
QTranslator *_translator;
QQmlEngine *_engine;
QGuiApplication *_app;
};
#endif // QMLTRANSLATOR_H
I'm not finding a way to pass DataloopWrapper::qmlInstanceas argument. At least it gives error in void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);on the qmlTranslator definition.
From a public: Members of DataloopWrapperi have the defenition of qmlInstance, it's this:
class DataloopWrapper : public QObject, public something::DataloopCBHandler,
public something::DataloopTransferCBHandler
{
Q_OBJECT
public:
explicit DataloopWrapper(QObject *parent = nullptr);
virtual ~DataloopWrapper();
static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new DataloopWrapper;
}
DataloopWrapper::qmlInstance is a function, that you need to call in order to get a pointer to a QObject.
For for any function you want to pass this object, you need to make it accept a pointer to a QObject (type QObject*), and don't forget to call DataloopWrapper::qmlInstance.
Translated into code:
class QmlTranslator : public QObject
{
...
void loadLanguage(QString language, QObject* objDataloop);
...
};
...
qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance(aQMLEngineObjectPointer, aQJSEnginePointer));
I have four files:
mainwindow.h
#pragma once // MAINWINDOW_H
#include <QMainWindow>
#include <QApplication>
#include "maincontent.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setStatusBarMessage(QString message);
signals:
public slots:
void exit();
private:
void setMenuBar();
MainContent* content;
};
maincontent.h
#pragma once // MAINCONTENT_H
#include "statistic.h"
#include "information.h"
#include <QWidget>
#include <QHBoxLayout>
class MainContent : public QWidget
{
Q_OBJECT
public:
explicit MainContent(QWidget *parent = nullptr);
signals:
public slots:
private:
QHBoxLayout* layout;
Statistic* statistic;
Information* financFlow;
};
information.h
#pragma once // INFORMATION_H
#include <QPushButton>
#include <QWidget>
//#include "mainwindow.h" //error
class Information : public QWidget
{
Q_OBJECT
public:
explicit Information(QWidget *parent = nullptr);
signals:
public slots:
private:
QPushButton* button;
};
statistic.h
#pragma once // STATISTIC_H
#include <QWidget>
#include <QHBoxLayout>
#include <QListView>
class Statistic : public QWidget
{
Q_OBJECT
public:
explicit Statistic(QWidget *parent = nullptr);
signals:
public slots:
private:
QListView* listView;
};
Now I will use the MainWindow::setStatusBarMessagemethod from the Information class.
But when I include the MainWindow in the Information class: #include "mainwindow.h"
I become the error: MainContent does not name a type in line 22 in mainwindow.h
First I don't know why the compiler can't find MainContent bacause in MainWindow I included the "maincontent.h", does the preprocessor only include "mainwindow.h" but not the "maincontent.h" in the "mainwindow.h"?
I see that with #include "mainwindow.h" a recursion arise but that shouldn't be a problem because of #pragma once or?
Next I tried to include the "mainwindow.h" in the information.cpp file but then I have the problem that I everytime give the MainWindow object by parameter and can't hold a MainWindow in my class
My main problem is that the MainWindow has a statusBar Object and I will set the statusBar message from everywhere. How can I do this, exist a Pattern or someting for that?
How can I solve this Problem or where I make a thinking mistake?
Thanks for your help.
You should use forward declaration for your included classes. Since pointers itself do not need to know a fully declared class (pointer size is always the same) you can easily get around this:
In header File instead of include the class just declare it:
#include <QMainWindow>
#include <QApplication>
//#include "maincontent.h" // REmove these
class MainContent;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setStatusBarMessage(QString message);
signals:
public slots:
void exit();
private:
void setMenuBar();
MainContent* content;
};
In cpp file now include the header again. Do this for all includes only having a pointer to given class.
As mentioned by #dempzorz removing the circular dependency is always prefered, but not always possible.
You have a circular dependency. You can't have information.h include mainwindow.h and also have mainwindow.h include information.h. You should design dependencies in a hierarchy, where items lower in the tree do not include items higher in the tree.
You should have a look at this link to maybe give you a better understanding of how to structure your objects:
https://en.wikipedia.org/wiki/Circular_dependency
I'm asking if there is a way to use signals in a class which inherits from QObject like this:
mysuperclass.cpp
#include "mysuperclass.h"
MySuperclass::MySuperclass(quint16 port, QObject *parent) :
QObject(parent), port(port)
{
this->connected = false;
}
mysuperclass.h
#include <QAbstractSocket>
class MySuperclass: public QObject
{
Q_OBJECT
public:
explicit MySuperclass(quint16 port = 0, QObject *parent = 0);
signals:
//there is nothing here
public slots:
virtual void newValue(){qDebug() << "newValue";}
virtual void connectionEstablished(){qDebug() << "connectionEstablished";}
virtual void disconnected(){qDebug() << "disconnected";}
protected:
QAbstractSocket* networkSocket;
quint16 port;
bool connected;
};
mysubclass.cpp
#include <QTcpSocket>
#include <QHostAddress>
MySubClass::MySubClass(quint16 ServerPort, QObject *parent) :
MySuperClass(ServerPort, parent)
{
this->networkSocket = new QTcpSocket(this);
...
connect(this->networkSocket, SIGNAL(connected()),this,
SLOT(connectionEstablished()));
connect(this->networkSocket, SIGNAL(disconnected()),this,
SLOT(disconnected()));
connect(this->networkSocket, SIGNAL(readyRead()),this, SLOT(newValue()));
}
mysubclass.h
#include <QObject>
#include "mysuperclass.h"
class MySubClass: public MySuperClass
{
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
You must include the Q_OBJECT macro in the derived class too (but don't derive from QObject again). The macro is only mandatory if the derived class declares signals or slots. For emitting parent's signals or connecting with parent's slots it is not necessary (it also means that it is not necessary to re-define already existing signals or slots).
From Qt's documentation:
The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
Example
class MySubClass : public MySuperClass {
Q_OBJECT
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
On the other hand, if you want to connect to a slot in the parent class but implement it in a derived one, then you must make it virtual:
class MySuperclass : public QObject {
Q_OBJECT
// ...
public slots:
virtual void newValue(); // can be virtual pure also
};
class MySubClass : public MySuperClass {
public:
virtual void newValue() override; // overrides parent's
}
Note that there is no need to use the Q_OBJECT macro nor to use the slot: label in the derived class. Slots are normal methods after all. Of course, you have to use it if you add new slots or signals.
This class no problem:
#include <QThread>
class LiveImageItem : public QThread
{
Q_OBJECT
public:
LiveImageItem(QPixmap pimg);
signals:
public slots:
};
BUT this class get problem associated with "Q_OBJECT" macro defined in header file
#include <QGraphicsPixmapItem>
class LiveImageItem : public QGraphicsPixmapItem
{
Q_OBJECT //this line will generate many errors in compiling
public:
LiveImageItem(QPixmap pimg);
signals:
public slots:
};
both their cpp file is the same:
#include "LiveImageItem.h"
LiveImageItem::LiveImageItem(QPixmap pimg)
{
}
I thought every QT object essentially inherited from QObject so if I inherit any of the subclass of QObject, I could have all the magics QObject offers. The 2nd version of the above (which is inherited from, say, QGraphicsPixmapItem) seems proved I was wrong. It turns out to be having lots of errors while compiling, all from moc files(automatically generated by QT). What happens?
Some of these errors are:
[qobject.h] error: 'QScopedPointer QObject::d_ptr' is
protected
[moc_LiveImageItem.cpp] error: within this context
...
According to the documentation QGraphicsPixmapItem is not a QObject, thus you cannot treat it as if it is. I would try to extend your class inheritance and do:
class LiveImageItem : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT //this line will generate many errors in compiling
[..]
As #vahancho said, QGraphicsPixmapItem is not a QObject. In fact, that can be said of most of the QGraphics*Item classes.
However, if you want to use signals and slots with QGraphicsSystem classes, you can inherit from QGraphicsObject: -
class LiveImageItem : public QGraphicsObject
{
Q_OBJECT
public:
private:
QPixmap m_pixmap;
};
You would then override the paint function in this class and draw the pixmap from there.