How is this Qt boilerplate constructor not recursive? - c++

So when you create a standard Qt5 widget application, this is the boilerplate code for the QMainWindow subclass:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
So the class has an instance of itself, that seems fine. But then that instance itself would have an instance of itself, which in turn would have an instance of itself...
How does this not lead to an infinite recursion of classes containing themselves?

These are not the same classes. MainWindow is declared in the global namespace, while the ui member is of type Ui::MainWindow, which is declared in the Ui namespace. You can see the declaration of this class by looking at ui_mainwindow.h.
Since these are two different types, no recursion will happen, since MainWindow::~MainWindow() will not be called from within itself.

Related

QT (C++) program crashes when adding widget to layout

When I try to add any new widget to layout my program crashes. What could be the problem?
I have a pointer to QLabel as a data member of MainWindow. In constructor I allocate memory for it and that try to add it to layout. I really don't know what is the problem, cause I did this method before and it worked.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QLabel* tempLabel;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
tempLabel = new QLabel("QLabel 2");
ui->widget->layout()->addWidget(tempLabel);
ui->setupUi(this);
}
MainWindow::~MainWindow() {
delete ui;
}
Error msg

Using object directly from another class c++

Hi i have 3 classes that i want to use. but i dont want to create object of one class more than once. I directly want to use the object (in third class) of one class declared and initialized in second class.
To understand the problem please focus on NetworkConnection members and class defined in example below.
Class Mainwindow header
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "secondscreen.h"
#include "networkconnection.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
NetworkConnection *NetworkConnectionObject;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
SecondScreen* SecondScreenObject;
};
#endif // MAINWINDOW_H
Class Main Window cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QMessageBox"
#include "networkconnection.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
NetworkConnectionObject = new NetworkConnection();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
int Error = NetworkConnectionObject->Connect(Username,Password);
///////////////
// This Works
//////////////
NetworkConnectionObject->LogInToken = "";
}
Class NetworkConnection Header
#ifndef NETWORKCONNECTION_H
#define NETWORKCONNECTION_H
#include <QString>
class NetworkConnection
{
public:
NetworkConnection();
int Connect(QString Username, QString Passwd);
QString LogInToken;
};
#endif // NETWORKCONNECTION_H
Now i want to use Networkclassobject directly in SeconScreenclass so that i can access LogInToken Member of MainWindowInstance.
#include "secondscreen.h"
#include "ui_secondscreen.h"
#include "mainwindow.cpp"
SecondScreen::SecondScreen(QWidget *parent) :
QDialog(parent),
ui(new Ui::SecondScreen)
{
ui->setupUi(this);
///////////////
// This doesnot work
//////////////
MainWindow::NetworkConnectionObject->LogInToken = "";
}
SecondScreen::~SecondScreen()
{
delete ui;
}
However, when i try this compiler says
Invalid use of non-static data member "MainWindow::NetworkConnectionObject" Problem is i dont want to declare it static. Is there any way to do it.
Without seeing secondscreen.h I can't say for sure but MainWindow::NetworkConnectionObject" doesn't reference a specific instance of MainWindow class, you must reference a specific instance to modify.
If in your SecondScreen header you have something like
class SecondScreen {
// . . .
MainWindow window;
// . . .
}
then in your constructor for SecondScreen you must use the initialized instance of MainWindow, i.e.
SecondScreen::SecondScreen(QWidget* parent) : QDialog(parent) {
window.NetworkConnectionObject->LogInToken = "";
}

Why can I use QSerialPort* as a temporary variable but not as a class' member in Qt 5.5.1?

I was trying to build a GUI for a project with an Arduino. The project itself is about a car-robot for harbor's containers management, and during the time it's on the development stage (and also on final release) would be cool to have a way to monitor and send commands to it. Seems a good idea to initially implement a communication via serial port and then rewrite/reuse the code for a radio communicator or something like that. The code was going well until some bugs come up.
First were used QSerialPort and QSerialPortInfo, following the example of several programs available at Qt's website. The compiler showed up with some errors about a missing "QT+=serialport" and about wrong forward declarations but after a while I could fix them. Then when the code to open a serial port was written, the program started to crash...
After some hours, this GUI Qt code (and a respective console version) works and exemplifies the problem:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/qserialport.h>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
QSerialPort *connected_port;
connected_port = new QSerialPort;
}
MainWindow::~MainWindow() {
delete ui;
}
main.cpp
#include <QApplication>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
However just after changing mainwindow.h and inserting QSerialPort *connected_port; in MainWindows's private section and removing it from mainwindow.cpp, this simple program starts to crash.
mainwindow.h
(...)
class MainWindow : public QMainWindow {
(...)
private:
QSerialPort *connected_port;
Ui::MainWindow *ui;
};
(...)
mainwindow.cpp
(...)
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
connected_port = new QSerialPort;
}
(...)
Will crash. In qt's terminal example is a similar approach, but I did not get the why it works and this code don't. How make it work?
Solved. For some reason, adding a "QT+=widgets" on the .pro file produced a functional program, aside the already added "QT+=serialport".

QT signal-slot not received

I am trying to connect a signal from a second QMainWindow to the mainwindow. It doesn't say anything about a problem connection when the program is launched, but It doesn't work. I am not very familiar with C++ and Qt so maybe is something simple.
My code consists on a Mainwindow used as a SCADA with Start, stop, On, off buttons. In the second qmainwindow I created a terminal where you can type, start,stop... There, I would like to emit a signal to my MainWindow which is in charge of controlling the multiple threads and windows. The problem is that I cannot connect to my slot. I present here a simple overview of this two pieces of code.
Terminal. h
#ifndef TERMINAL__H
#define TERMINAL__H
#include <QMainWindow>
#include <QTextEdit>
#include <QLineEdit>
#include <QObject>
namespace Ui {
class Terminal_;
}
class Terminal_ : public QMainWindow
{
Q_OBJECT
public:
explicit Terminal_(QWidget *parent = 0);
~Terminal_();
signals:
void turnonPLC_terminal();
public slots:
void newline();
private:
Ui::Terminal_ *ui;
QTextEdit* mTerminal;
QLineEdit* mInput;
};
#endif // TERMINAL__H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "terminal_.h"
#include "terminal_help.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Terminal_ *terminal;
public slots:
void turnon_terminal();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "terminal_.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
terminal = new Terminal_(this);
connect(terminal, SIGNAL(turnonPLC_terminal()), this, SLOT(turnon_terminal()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::turnon_terminal(){
turnonPLC=1;
}
terminal_.cpp
#include "terminal_.h"
#include "ui_terminal_.h"
#include <QDockWidget>
#include <QWidget>
#include <QLineEdit>
QString on=("on");
Terminal_::Terminal_(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Terminal_)
{
ui->setupUi(this);
mTerminal = new QTextEdit();
setCentralWidget(mTerminal);
mInput = new QLineEdit();
QDockWidget* qdw = new QDockWidget;
qdw->setWidget(mInput);
addDockWidget(Qt::BottomDockWidgetArea, qdw);
connect (mInput, SIGNAL(returnPressed()),
this, SLOT(newline()));
}
Terminal_::~Terminal_()
{
delete ui;
}
void Terminal_::newline(){
QString command = mInput->text();
if (command==on){
emit turnonPLC_terminal();
}
}
Thanks
The signal-slots part in the code works perfectly. (compiled and tested with some small modifications)
After entering "on" (not On as written in question)
Terminal_::newline() slot called, turnonPLC_terminal() is fired and finally
void MainWindow::turnon_terminal() is called.
However, there are some small details the header file is called terminal_.h, not Terminal.h turnonPLC is not defined. terminal is created by not displayed (no show-call).
I guess, there are simply some many small logic errors. Try to use debugger or trace the chain of expected calls with qDebug.

ERROR: 'abc' does not have a name type QT c++ GUI application

bottom line is i have 2 forms , first mainwindow 2nd form1 . i have a button on mainwindow that displays form 2 . now i have a button on form1 that should take me to mainwindow but it is not working. problem is when i say #include in form1.h it gives me an error i.e mainwindow does not have a name type. please help , working example would be great if possible . Actual error is MainWindow does not have a name type
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <form1.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui; // i put this line of code in public section when i was trying ui->show(); in form1.cpp file
Form1 obj ; // to show next form
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
obj.show();
this->hide();
}
Form1.h
#ifndef FORM1_H
#define FORM1_H
#include <QWidget>
#include<mainwindow.h>
namespace Ui {
class Form1;
}
class Form1 : public QWidget
{
Q_OBJECT
public:
explicit Form1(QWidget *parent = 0);
~Form1();
private slots:
void on_pushButton_clicked();
private:
Ui::Form1 *ui;
MainWindow mw ; // here i am making object of main window
};
#endif // FORM1_H
form1.cpp
#include "form1.h"
#include "ui_form1.h"
#include<mainwindow.h> // i know when i include this there this issue occurs , but i want to go my previous form to show and for that i have to make its object ! thats how it works when i am going to my next form i.e form1 now i want to go back
Form1::Form1(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form1)
{
ui->setupUi(this);
}
Form1::~Form1()
{
delete ui;
}
void Form1::on_pushButton_clicked() // show mainWindow
{
mw->show();
this->hide();
//MainWindow::ui->show(); // i even tried this
}
i also tried if i could do it without including mainwindow.h in form1.h by puttin Ui::MainWindow *ui; in public section so form1.cpp file i could access it by typing MainWindow::ui->show(); this time ERROR says Object is missing Reference to 'MainWindow::ui'
You have a circular dependency between the classes MainWindow and Form1. Thus, you include form1.h in mainwindow.h and mainwindow.h in form1.h. When the compiler reaches the line
MainWindow mw ; // here i am making object of main window
it is the first time he encounters the symbol MainWindow and trigger that error.
I still don't understand why mw is a member of Form1, but you can break the dependency using a pointer instead. Basically you will now have
MainWindow* mw ;
And rather than #include<mainwindow.h> in Form1.h you will just have to forward declare
class MainWindow;