Use class A which includes class B from class B - c++

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

Related

C++ Qt4.8 :: Pass Object to another Class - member access into incomplete type error

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.

QT: Error [expected ")" before "*" token and MainWindow does not name a type]

I got two errors in Qt, I wish you can help me with this. This is my first time I post something, please me help. This is the code:
#include <QMainWindow>
#include "mainwindow.h"
#include <QThread>
#include <QtCore>
#include "ui_mainwindow.h"
class HiloPrincipal : public QThread
{
Q_OBJECT
public:
explicit HiloPrincipal( MainWindow* parent = 0); // First error
MainWindow * _parent; // Second error
void run(); // Sacar Botella y poner botella.
signals:
public slots:
};
#endif // HILOS_H
I almost sure you have created include cycle.
Fix it like this:
#ifndef HILOS_H // this was missing! Probably when you did copy paste to question
#define HILOS_H
#include <QMainWindow>
// remove line: #include "mainwindow.h"
#include <QThread>
#include <QtCore>
// remove line: #include "ui_mainwindow.h"
// forward declaration
class MainWindow;
class HiloPrincipal : public QThread
{
Q_OBJECT
public:
explicit HiloPrincipal( MainWindow* parent = 0); // First error
MainWindow * _parent; // Second error
void run(); // Sacar Botella y poner botella.
signals:
public slots:
};
#endif // HILOS_H
Than include this headers files mainwindow.h in HiloPrincipal.cpp. This should solve build issue, but not actual problem.
Note problem is caused by invalid design of classes. Your HiloPrincipal thread shouldn't have any knowledge about MainWindow.
Also you're doing that wrong - this is invalid use of QThread.

Passing the parent pointer in Qt | ERROR: no member named in QObject

I am new to qt and I am trying to create a program where the MainWindow calls a QDialog to enter some data.
The problem is that the parent() at my QDialog does not have any access to the public methods of the MainWindow in our case the
void save_city(const City *city); //public method of MainWindow
The code is actually big so here is some of the code.Thanks.
mainwindow.h
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMainWindow>
#include <QTextStream>
#include <QVector>
#include <QDebug>
#include <QFile>
#include "dialog_add_city.h"
#include "street.h"
#include "city.h"
#include "map.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//main Window constructor
explicit MainWindow(QWidget *parent = 0);
//main Window deconstructor
~MainWindow();
/*utility function to save the city
*the function is public so that also QDialogs
*data saves can */
//////////////
//here is the public function
void save_city(const City *city);
private slots:
private:
Map mainMap;
Ui::MainWindow *ui;
QGraphicsView view;
QGraphicsScene scene;
};
dialog_add_city.h
#ifndef DIALOG_ADD_CITY_H
#define DIALOG_ADD_CITY_H
#include <QDialog>
#include "mainwindow.h"
#include "City.h"
namespace Ui {
class Dialog_Add_City;
}
class Dialog_Add_City : public QDialog
{
Q_OBJECT
public:
explicit Dialog_Add_City(QWidget *parent = 0);
~Dialog_Add_City();
private slots:
//Add New City Button clicked-Adds an new city to our city_locations.txt
void on_PushButton_Add_New_City_clicked();
private:
Ui::Dialog_Add_City *ui;
};
#endif // DIALOG_ADD_CITY_H
dialog_add_city.cpp
#include "dialog_add_city.h"
#include "ui_dialog_add_city.h"
Dialog_Add_City::Dialog_Add_City(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog_Add_City)
{
ui->setupUi(this);
}
Dialog_Add_City::~Dialog_Add_City()
{
delete ui;
}
void Dialog_Add_City::on_PushButton_Add_New_City_clicked()
{
City *city=new City(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
qDebug() << ui->lineEdit_cityName->text()
<< ui->lineEdit_X_Ko->text()
<< ui->lineEdit_Y_Ko->text();
/////////////////////////////
//HERE IS THE PROBLEM
parent()->save_city(city);
}
Any other suggestions are welcomed!
The Problem is that parent() will return a pointer the parent object as QObject.
QObject Documentation
As dreschrjm pointed out you could try to cast the object via
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
from The Meta-Object System
Suggestion: Use Qt's signal/slot mechanism to avoid a backward reference to the parent.
Declare save_city as signal in Dialog_Add_City.
Declare save_city in MainWindow as slot
Connect both where the dialog is created:
e.g.
void MainWindow::show_add_city_dialog()
{
Dialog_Add_city dialog;
connect(&dialog, &Dialog_Add_city::save_city, this, &MainWindow::save_city);
dialog.exec();
}
Replace parent()->save_city(city); in Dialog_Add_City with emit save_city(city);
Ensure that the new city object doesn't leak, I think a better design would be to create the City object elsewhere not in the dialog.
so
emit save_city(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
and the slot
void MainWindow::save_city(const QString &cityName, double x, double y)
{
City *city=new City(cityName, x, y);
// do some interresting things with city.
}

How to open a new QDailog window when an element in the menu bar is clicked in Qt C++

Material class has a mainwindow with a menu bar. When i click one of the elements in the menu bar i want to open the Fiction Qdialog window.
material.h
#ifndef MATERIALS_H
#define MATERIALS_H
#include <QMainWindow>
#include "materialinner.h"
class FictionSection;
namespace Ui {
class Materials;
}
class Materials : public QMainWindow, public MaterialInner
{
Q_OBJECT
public:
explicit Materials(QWidget *parent = 0);
~Materials();
private:
Ui::Materials *ui;
FictionSection *fiction;
};
#endif // MATERIALS_H
materials.cpp
#include "materials.h"
#include "ui_materials.h"
#include "fictionsection.h"
#include <QDebug>
#include <QMessageBox>
Materials::Materials(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Materials)
{
ui->setupUi(this);
// connect(ui->ficti,SIGNAL(textChanged(const QString &)),this,SLOT(displaySearch()));
}
Materials::~Materials()
{
delete ui;
}
void Materials::on_actionFiction_section_triggered()
{
this->hide();
fiction = new FictionSection();
fiction->show();
}
fictionsection.h
#ifndef FICTIONSECTION_H
#define FICTIONSECTION_H
#include <QDialog>
#include "materials.h"
namespace Ui {
class FictionSection;
}
class FictionSection : public QDialog, public Materials
{
Q_OBJECT
public:
explicit FictionSection(QWidget *parent = 0);
~FictionSection();
private:
Ui::FictionSection *ui;
};
#endif // FICTIONSECTION_H
When i compile it gives an error which is
Request for member 'show' is ambiguous.
Please help me to solve this. Thank you in advance.
The problem is that your FictionSection class inherits from both QDialog and Materials, but your Materials class also inherits from QMainWindow. Both QMainWindow and QDialog have a virtual show() method (inherited from QWidget), which causes the ambiguity. In other words: do you intend to call QMainWindow::show's implementation or QDialog::show's implementation? No one knows.
To solve this, you should use inheritance properly. Inherit from either QMainWindow or QDialog, but not both.
You need to understand why it is that you're inheriting the way you are (which is wrong) and improve the logic of the relationship between your classes to avoid problems like this one.
Also, class names should be singular, so Materials should be Material. If it needs to handle multiple things, then it could be MaterialManager or something similar.

Transmitting data between classes

My code is set up in this way: the main window with a QTableWidget, and a control panel created with a different class from the MainWindow. In the control panel control there is a QListWidget where I want to load the titles of the header from the table, but being QTableWidget private, how can I pass data between the two classes?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "QControlPanel.h"
#include <QMainWindow>
#include <QWidget>
#include <QtGui>
#include <QTableWidget>
namespace Ui {
class MainWindow;
class GenerateXML;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
private:
Ui::MainWindow *ui;
QTableWidget* m_pTableWidget;
QControlPanel* preferences;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setWindowIcon(QIcon("DrawItem.ico"));
this->setWindowTitle("DrawItem");
resize(890, 475);
m_pTableWidget = new QTableWidget(this);
m_TableHeader<<"A"<<"B"<<"C"<<"D"<<"E";
m_pTableWidget->setHorizontalHeaderLabels(m_TableHeader);
m_pTableWidget->resizeColumnsToContents();
m_pTableWidget->verticalHeader()->setVisible(false);
m_pTableWidget->move(30, 75);
m_pTableWidget->resize(410, 151);
preferences = new QControlPanel(this);
}
QControlPanel.h
#include <QDialog>
#include <QTableWidget>
#ifndef QCONTROLPANEL_H
#define QCONTROLPANEL_H
class QControlPanel : public QDialog
{
Q_OBJECT
public:
explicit QControlPanel(QWidget *parent = 0);
~QControlPanel();
public slots:
void customHeader(QTableWidget *table);
private:
QListWidget *headerlist;
private slots:
};
#endif
QControlPanel.cpp
#include "QControlPanel.h"
QControlPanel::QControlPanel(QWidget *parent) :
QDialog(parent)
{
headerlist = new QListWidget(inputHeader);
headerlist->setGeometry(140, 15, 140, 130);
}
You can have a signal in the QControlPanel class which retrieves the headers. So QControlPanel can be like :
class QControlPanel : public QDialog
{
Q_OBJECT
public:
explicit QControlPanel(QWidget *parent = 0);
~QControlPanel();
signals:
QStringList getHeaders();
private:
QListWidget *headerlist;
};
And connect the getHeaders() signal to a slot of the class which contains the list of columns to retrieve them. This should be done in the constructor of the MainWindow :
connect(preferences,SIGNAL(getHeaders()),this,SLOT(getTableHeader()));
getTableHeader() is a slot in MainWindow which return the header columns :
QStringList getTableHeader()
{
return m_TableHeader;
}
Now you can access the headers in QControlPanel :
QControlPanel::QControlPanel(QWidget *parent) :
QDialog(parent)
{
headerlist = new QListWidget();
headerlist->insertItems(0, getHeaders());
}