Reputation: 567
I have an error, just after closing my application, I get an error message saying that it has stopped unexpectedly. I reached this:
But, after I close the window, I get this error:
The program has unexpectedly finished. The process was ended forcefully.
My project structure is:
And my code is:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <windows/login.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Login w;
w.show();
return a.exec();
}
util_window.h
#ifndef UTIL_H
#define UTIL_H
#include <QObject>
#include <QMainWindow>
class UtilWindow : QObject
{
public:
// vars
// methods
util();
void setCenterWindow(QMainWindow* w);
};
#endif // UTIL_H
util_window.cpp
#include "util_window.h"
#include <QDesktopWidget>
UtilWindow::util()
{
}
void UtilWindow::setCenterWindow(QMainWindow *w) {
int width = w->frameGeometry().width();
int height = w->frameGeometry().height();
QDesktopWidget wid;
int screenWidth = wid.screen()->width();
int screenHeight = wid.screen()->height();
w->setGeometry((screenWidth/2)-(width/2),(screenHeight/2)-(height/2),width,height);
w->show();
}
login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QMainWindow>
#include <QObject>
#include <QWidget>
#include "util/util_window.h"
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QFormLayout>
class Login : public QMainWindow
{
Q_OBJECT
public:
// vars
UtilWindow* util;
// widgets
// labels
QLabel* lblHost;
QLabel* lblPort;
QLabel* lblUser;
QLabel* lblPass;
// textbox
QLineEdit* leHost;
QLineEdit* lePass;
QLineEdit* leUser;
QLineEdit* lePort;
// layouts
QFormLayout* layout;
QWidget* central;
QVBoxLayout* mainLayout;
QGroupBox* gbCredentials;
// methods
void initLabels();
void initTextBoxes();
void initUI();
explicit Login(QWidget *parent = nullptr);
~Login();
signals:
public slots:
};
#endif // LOGIN_H
login.cpp
#include "login.h"
Login::Login(QWidget *parent) : QMainWindow(parent)
{
this->util = new UtilWindow();
this->initUI();
}
Login::~Login() {
delete this->lblHost;
delete this->lblPass;
delete this->lblPort;
delete this->lblUser;
delete this->leHost;
delete this->lePass;
delete this->lePort;
delete this->leUser;
delete this->layout;
delete this->central;
delete this->mainLayout;
delete this->gbCredentials;
delete this->util;
}
void Login::initUI() {
this->setFixedSize(400,400);
this->setWindowTitle(tr("Inicio de sesión"));
this->util->setCenterWindow(this);
this->initLabels();
this->initTextBoxes();
this->layout = new QFormLayout();
this->layout->addRow(this->lblHost, this->leHost);
this->layout->addRow(this->lblPort, this->lePort);
this->layout->addRow(this->lblUser, this->leUser);
this->layout->addRow(this->lblPass, this->lePass);
this->gbCredentials = new QGroupBox();
this->gbCredentials->setTitle(tr("Datos de conexión"));
this->gbCredentials->setLayout(layout);
this->mainLayout = new QVBoxLayout();
this->mainLayout->addWidget(gbCredentials);
this->central = new QWidget();
this->central->setParent(this);
this->central->setLayout(this->mainLayout);
this->setCentralWidget(this->central);
}
void Login::initLabels() {
this->lblHost = new QLabel();
this->lblPass = new QLabel();
this->lblPort = new QLabel();
this->lblUser = new QLabel();
this->lblHost->setText(tr("Host: "));
this->lblPass->setText(tr("Contraseña: "));
this->lblPort->setText(tr("Puerto: "));
this->lblUser->setText(tr("Usuario: "));
}
void Login::initTextBoxes() {
this->leHost = new QLineEdit();
this->lePass = new QLineEdit();
this->lePort = new QLineEdit();
this->leUser = new QLineEdit();
this->leHost->setPlaceholderText(tr("Host de MySQL"));
this->lePass->setPlaceholderText(tr("Ingrese su contraseña"));
this->leUser->setPlaceholderText(tr("Ingrese su nombre de usuario"));
this->lePort->setPlaceholderText(tr("Ingrese el número de puerto"));
this->leHost->setToolTip(this->leHost->placeholderText());
this->leUser->setToolTip(this->leUser->placeholderText());
this->lePass->setToolTip(this->lePass->placeholderText());
this->lePort->setToolTip(this->lePort->placeholderText());
}
Thanks in advance!
Upvotes: 2
Views: 2965
Reputation: 4111
You have deleting QMainWindow
elements by yourself :
delete this->lblHost;
When your QObject
inherited objects are created on heap with parent, you should not delete it by yourselves. because QObject
tree will take care of the memory memory management.
So twice deleting would be happen.
Upvotes: 0
Reputation: 10047
When you add widgets to a layout, e.g.
this->layout.addRow(&(this->lblHost), &(this->leHost));
you're parenting them to the layout's widget, in this case your Login main window, and when the parent widget destructor will be called, all children widget will be delete
'd. What happens in your code is: the children (line edits and labels) are not instantiated with new
, so calling delete on them will crash your application. You should replace the children declarations in your widget header with pointers, this way:
QLabel * lblHost;
// ...
QLineEdit * leHost;
// etc
and instantiate them before adding them to the layout:
this->lblHost = new QLabel();
this->leHost = new QLineEdit();
this->layout.addRow(this->lblHost, this->leHost);
//etc
This applies to all layouts and widgets that have a parent (i.e. central Qwidget).
Also: explicitly calling delete
on children is not needed, because the parent destructor will take care of that, and this applies to the central widget as well:
QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time
As thuga points out in comments, there is nothing inherently wrong in instantiating children on the stack, as long as their destructor is called before their parent's, thus they are automatically removed from the parent's children list and the parent destructor will not call delete
on them.
As explained here, this is legit:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QLabel label(&widget);
widget.show();
return a.exec();
}
because label
will go out of scope before widget
.
Changing the two objects creation order will cause the application crash at exit time:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLabel label;
QWidget widget;
label.setParent(&widget);
widget.show();
return a.exec();
}
Upvotes: 7