I`m still stuck.
I have a GUI-class that creates an Object. From a method of this new Object I want to use methods of the creating class
I have a Gui(PBV) with line_Edits and a Combobox. In this Combobox I can choose between different Geometries. Geo_1, Geo_2,… that inherit from Geometry. According to the entries in the combobox I want to create different Objects (Geo_1,Geo_2,…) that then set the lineEdits of the creating class according to the needs of the Geo_n-Object.
I don`want to do that with signal-slot
I asked different questions on that but I can`t get further.
I somehow feel this is kind of recursive... Is there a solution fort hat?
Here is my code:
PBV.h:
#include "../Geometry/Geo_1.h"
class PBV : public Tab
{
Q_OBJECT
public:
explicit PBV (QWidget *parent = 0);
~ PBV ();
virtual void printContent( QStringList *const qsl);
private:
Geo_1 *GEO_1;
Geometry *GEO;
}
PBV.cpp:
…
Geo_1 *GEO_1;
GEO_1 = new Geo_1(this);
GEO_1->set_LNE_default();
…
.
Geo_1.h:
#ifndef GEO_1_H
#define GEO_1_H
#include "Geometry.h"
#include "../Tabs/PBV.h"
class Geo_1: public Geometry
{
Q_OBJECT
public:
Geo_1 (QObject *_parent = 0);
virtual void set_LNE_default();
};
#endif // GEO_1_H
.
Geo_1.cpp:
#include "Geometry.h"
#include <QDebug>
#include "Geo_1.h"
#include "../Tabs/PBV.h"
Geo_1::Geo_1(QObject*_parent)
: Geometry(_parent) {}
void Geo_1::set_LNE_default()
{
// here I want to use printContent
}
.
Geometry.h:
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include <QObject>
class Geometry : public QObject
{
Q_OBJECT
public:
Geometry(QObject *_parent=0);
~Geometry();
virtual void set_LNE_default();
};
#endif // GEOMETRY_H
.
Geometry.cpp:
#include "Geometry.h"
#include <QDebug>
Geometry::Geometry(QObject *_parent)
: QObject(_parent) {}
Geometry::~Geometry(){}
void Geometry::set_LNE_default() { }
When PBV allocates a Geo_1 instance, it is already passing a pointer to itself in the constructor:
GEO_1 = new Geo_1(this); // "this" is your PBV instance
Why not save the pointer to use later?
Geo_1::Geo_1(PBV*_parent) : Geometry((QObject*)_parent)
{
this->pbv = _parent; // Save reference to parent
}
Then you can do:
void Geo_1::set_LNE_default()
{
// here I want to use printContent
this->pbv->printContent(...); // this->pbv is your saved ptr to the PBV that created this instance
}
EDIT
Additonally, you might run into the problem that you will have to cross-include the two headers (PBV and Geo_1), to fix this, remove the include for Geo_1 from PBV.h and forward-declare Geo_1. Just like this:
class Geo_1;
Before declaring your PBV class.
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.
I am new in C++ Qt and struggling with the correct use of forward declarations and #include.
What I want to do:
I have a Qt Gui (Class Ui::Gui) where we can set values.
I want to save these values in Gui Class variables.
As soon as a button (Generate Xml) is clicked, I want to pass the object
'ui' to the XmlGeneratorClass, So i can use the values to generate a Xml.
gui.h
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include <QDebug>
#include "xmlgeneratorqobject.h"
namespace Ui {
class Gui;
}
class Gui : public QMainWindow
{
Q_OBJECT
public:
explicit Gui(QWidget *parent = nullptr);
~Gui();
qint8 testvalue = 1;
signals:
void transmitToXmlGen(Ui::Gui*);
private slots:
void on_pushButtonGenerateXml_clicked();
private:
Ui::Gui *ui;
XmlGeneratorQObject *xmlgenerator = new XmlGeneratorQObject();
};
#endif // GUI_H
gui.cpp
#include "gui.h"
#include "ui_gui.h"
Gui::Gui(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Gui)
{
ui->setupUi(this);
connect(this,SIGNAL(transmitToXmlGen(Ui::Gui*)),xmlgenerator,SLOT(receiveFromGui(Ui::Gui*)));
}
Gui::~Gui()
{
delete ui;
}
void Gui::on_pushButtonGenerateXml_clicked()
{
emit transmitToXmlGen(ui);
}
xmlgeneratorqobject.h
#ifndef XMLGENERATORQOBJECT_H
#define XMLGENERATORQOBJECT_H
#include <QObject>
#include <QDebug>
namespace Ui {
class XmlGeneratorQObject;
class Gui;
}
class XmlGeneratorQObject : public QObject {
Q_OBJECT
public:
explicit XmlGeneratorQObject(QObject * parent = nullptr);
private slots:
void receiveFromGui(Ui::Gui*);
};
#endif // XMLGENERATORQOBJECT_H
xmlgeneratorqobject.cpp
#include "xmlgeneratorqobject.h"
XmlGeneratorQObject::XmlGeneratorQObject(QObject *parent){}
void XmlGeneratorQObject::receiveFromGui(Ui::Gui* objectFromGui)
{
qDebug() << objectFromGui->testvalue; // ERROR member access into incomplete type 'Ui::Gui'
}
Expected result:
Access to public variables from passed gui-object should be possible
Actual result:
member access into incomplete type 'Ui::Gui'
Can you please help me learn forward declaration / include?
Is my approach in general okay?
Your xmlgeneratorqobject.cpp needs the line
#include "ui_gui.h"
This gives it the details of the ui widgets. This file is generated by the Qt build system.
I have two classes: HoodPlanner and DrawRoad. Both classes inherit from QWidget and the the UI so I can access all UI elements in both classes.
Here's a snipped of both classes:
HoodPlanner:
#ifndef HOODPLANNER_H
#define HOODPLANNER_H
#include <ui_hoodplanner.h>
#include "drawroad.h"
#include <QtWidgets>
class HoodPlanner : public QWidget, private Ui::HoodPlanner
{
Q_OBJECT
private:
// (...)
public:
explicit HoodPlanner(QWidget * = 0);
// (...)
private slots:
// (...)
};
#endif // HOODPLANNER_H
DrawRoad:
#ifndef DRAWROAD_H
#define DRAWROAD_H
#include <ui_hoodplanner.h>
#include <QtWidgets>
class DrawRoad : public QWidget, private Ui::HoodPlanner
{
Q_OBJECT
private:
// (...)
public:
explicit DrawRoad(QWidget *parent = 0);
public slots:
void drawSC4Street();
};
#endif // DRAWROAD_H
In HoodPlanner I have a connect that will be emitted whenever the itemSelection changes in table_ts2. I have the slot stored in DrawRoad, but inserting a reference to the DrawRoad object in third position brings up errors.
HoodPlanner::HoodPlanner(QWidget *parent) : QWidget(parent)
{
setupUi(this);
// (...)
DrawRoad *drawRoad = new DrawRoad;
connect(table_ts2, SIGNAL(itemSelectionChanged()), &drawRoad, SLOT(drawSC4Street()));
}
Snipped from DrawRoad.cpp:
#include "drawroad.h"
DrawRoad::DrawRoad(QWidget *parent) : QWidget(parent)
{
}
void DrawRoad::drawSC4Street()
{
if(!table_ts2->selectionModel()->hasSelection()) return;
// (...)
}
And the following errors occur whenever I run the app:
hoodplanner.cpp:12: Fehler: no matching function for call to 'HoodPlanner::connect(QTableWidget*&, const char [24], DrawRoad**, const char [17])'
mingw492_32\include\QtCore\qobject.h:213: Fehler: no type named 'Object' in 'struct QtPrivate::FunctionPointer<const char*>'
(and lots of notes)
The errors don't help me at all and I've searched in several topics for a solution, but none of them had my problem.
Have you tried
HoodPlanner::HoodPlanner(QWidget *parent) : QWidget(parent)
{
setupUi(this);
// (...)
DrawRoad *drawRoad = new DrawRoad;
connect(table_ts2, SIGNAL(itemSelectionChanged()), drawRoad, SLOT(drawSC4Street()));
}
You declrared drawRoad as a pointer:
DrawRoad *drawRoad = new DrawRoad;
And then you pass its address to connect() with &drawRoad.
In this case you are passing a pointer to a pointer address. Try without the &
I have a question again:
I have a class PBV t(inherits from Tab) hat has a class Geometry. Geometry is the parent of Geo_1. From Geo_1 I want to have access to methods of PBV ( e.g. printContent . How do I do that? I am able to create Signal-Slots but since I have to use methods of PBV often that would make lots of Signal-Slots.
Here is my code:
PBV.h:
#include "../Geometry/Geo_1.h"
class PBV : public Tab
{
Q_OBJECT
public:
explicit PBV (QWidget *parent = 0);
~ PBV ();
virtual void printContent( QStringList *const qsl);
private:
Geo_1 *GEO_1;
Geometry *GEO;
}
PBV.cpp:
…
Geo_1 *GEO_1;
GEO_1 = new Geo_1(this);
GEO_1->set_LNE_default();
…
.
Geo_1.h:
#ifndef GEO_1_H
#define GEO_1_H
#include "Geometry.h"
#include "../Tabs/PBV.h"
class Geo_1: public Geometry
{
Q_OBJECT
public:
Geo_1 (QObject *_parent = 0);
virtual void set_LNE_default();
};
#endif // GEO_1_H
.
Geo_1.cpp:
#include "Geometry.h"
#include <QDebug>
#include "Geo_1.h"
#include "../Tabs/PBV.h"
Geo_1::Geo_1(QObject*_parent)
: Geometry(_parent) {}
void Geo_1::set_LNE_default()
{
// here I want to use printContent
}
.
Geometry.h:
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include <QObject>
class Geometry : public QObject
{
Q_OBJECT
public:
Geometry(QObject *_parent=0);
~Geometry();
virtual void set_LNE_default();
};
#endif // GEOMETRY_H
.
Geometry.cpp:
#include "Geometry.h"
#include <QDebug>
Geometry::Geometry(QObject *_parent)
: QObject(_parent) {}
Geometry::~Geometry(){}
void Geometry::set_LNE_default() { }
One approach, as referred to by comments, is to keep track of the parent class in the constructor of the child:
In Geometry.h, add a private member variable:
private:
PBV* m_pParentPBV;
Then, in the constructor in Geometry.cpp, set this to the parent you are already passing:
Geometry::Geometry(QObject *_parent)
: QObject(_parent)
{
m_pParentPBV = dynamic_cast<PBV*>(_parent);
}
Now you can call methods on the parent using m_pParentPBV->printContent() etc.
I recently started programming in C ++ and am having some difficulties in relation to the exchange of data between classes.
I searched many tutorials and examples, but none worked. I finally decided to ask for help because I do not know what do ...
PS: I want to call keyPressEvent function from my B (solEditor) class
thanks.
addons/soleditor.h (class)
#include <Qsci/qsciscintilla.h>
#include <QWidget>
#include <QKeyEvent>
class Editor; // main class
class solEditor : public QsciScintilla
{
public:
explicit solEditor(QWidget *parent = 0);
Editor editor; // error <<
protected:
void keyPressEvent(QKeyEvent *e);
};
editor.h (main window)
#include <QMainWindow>
#include "about.h"
#include "data.h"
#include "addons/codeeditor.h"
#include "addons/highlighter.h"
#include "addons/soleditor.h"
#include "plugins/headergenerator.h"
#include "plugins/updatescreen.h"
namespace Ui {
class Editor;
}
class solEditor;
class Editor : public QMainWindow
{
Q_OBJECT
solEditor *sE;
public:
QsciScintilla* ce;
Highlighter *Hl;
solEditor *e;
Ui::Editor *ui;
explicit Editor(QWidget *parent = 0);
~Editor();
public slots:
void on_KeyPress(QKeyEvent *e);
};
Error:
SOLEditor\addons\soleditor.h:14: error: C2079: 'solEditor::editor' uses undefined class 'Editor'
You are using a forward declaration
class Editor; // main class
with a local instance of that class
Editor editor; // error <<
Unfortunately, that is not possible, as in this case the compiler needs to know the full details of the Editor class.
There are two possible solutions:
Make the member a pointer: Editor* editor
Use an #include instead of a forward declaration.
If you want to make your code flexible, you could do it like this:
class solEditor : public QsciScintilla
{
public:
explicit solEditor(Editor* editor, QWidget* parent = 0);
inline Editor* editor() const { return _editor; }
private:
Editor* _editor;
}
and in the cpp file:
solEditor::solEditor(Editor* editor, QWidget* parent)
// TODO: call parent constructor
{
_editor = editor;
}
solEditor::~solEditor()
{
_editor = NULL;
}
You can then create a solEditor instance like this:
QWidget* optionalParentWidget = GetParentWidgetFromSomewhere();
Editor* editor = GetEditorInstanceFromSomewhere(); // or create it yourself
solEditor* myEditor = new solEditor(editor, optionalParentWidget);
(As a side node, classes in C++ usually start with a capital letter: QWidget, Editor, SolEditor. That makes it easier to spot if something is a class, a function or a variable).
About the key press event: If you want one class to handle certain events of another class, it's best to use the eventFilter mechanism:
http://qt-project.org/doc/qt-5/qobject.html#installEventFilter