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!
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();
}
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.
Related
I am doing a qt project, my goal is to draw something based on my input. The signal is in the main, and the drawing is in another object, I am not able to connect them.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Frequency fre; //this is the class that does the drawing
QWidget *window = new QWidget;
QGridLayout *grid = new QGridLayout;
QGroupBox *groupBox = new QGroupBox(QObject::tr("Volume"));
QSpinBox *spinBox = new QSpinBox;
spinBox->setRange(0, 5);
QObject::connect(spinBox, SIGNAL(valueChanged(int)),&fre, SLOT(setVolume(int)));
QVBoxLayout *Vbox = new QVBoxLayout;
Vbox->addWidget(spinBox);
groupBox->setLayout(Vbox);
grid->addWidget(groupBox, 4,7,1,1);
window->setLayout(grid);
window->show();
return app.exec();
}
This is how I set up the Frequency class :
in h file
class Frequency : public QGLWidget
{
Q_OBJECT
public slots:
void setVolume(int value);
in cpp file
void Frequency :: setVolume(int val) {
vol = val;
updateGL();
}
void Frequency :: paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
}
Since I can't put all this in the comment section, I'm going to put it here:
I copied your code and I'm not able to reproduce the error with Qt version 5.14.0, because when I change the value in any way, the method, void MyObject::setVolume(int value) is being called.
This code should work for you. Possibly, you are running it in release mode, and used a breakpoint to check if it was called (which doesn't always work on release mode).
// #include "QtWidgetsApplication4.h"
#include <QtWidgets/QApplication>
#include "MyObject.h"
#include <QGridLayout>
#include <QGroupBox>
#include <QSpinBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QtWidgetsApplication4 w;
// w.show();
// return a.exec();
MyObject object;
QWidget* window = new QWidget;
QGridLayout* grid = new QGridLayout;
QGroupBox* groupBox = new QGroupBox(QObject::tr("Volume"));
QSpinBox* spinBox = new QSpinBox;
spinBox->setRange(0, 5);
QObject::connect(spinBox, SIGNAL(valueChanged(int)), &object, SLOT(setVolume(int)));
QVBoxLayout* Vbox = new QVBoxLayout;
Vbox->addWidget(spinBox);
groupBox->setLayout(Vbox);
grid->addWidget(groupBox, 4, 7, 1, 1);
window->setLayout(grid);
window->show();
return a.exec();
}
#pragma once
#include <QObject>
class MyObject : public QObject
{
Q_OBJECT
public slots:
void setVolume(int value);
private:
int m_volume;
};
#include "MyObject.h"
void MyObject::setVolume(int value)
{
m_volume = value;
}
I have a custom widget with some standard child widgets inside. If I make a separate test project and redefine my custom widget to inherit QMainWindow, everything is fine. However, if my custom widget inherits QWidget, the window opens, but there are no child widgets inside.
This is the code:
controls.h:
#include <QtGui>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
class Controls : public QWidget
{
Q_OBJECT
public:
Controls();
private slots:
void render();
private:
QWidget *frame;
QWidget *renderFrame;
QVBoxLayout *layout;
QLineEdit *rayleigh;
QLineEdit *mie;
QLineEdit *angle;
QPushButton *renderButton;
};
controls.cpp:
#include "controls.h"
Controls::Controls()
{
frame = new QWidget;
layout = new QVBoxLayout(frame);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
frame->setLayout(layout);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
main.cpp:
#include <QApplication>
#include "controls.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Controls *controls = new Controls();
controls->show();
return app.exec();
}
This opens up a window with correct dimensions, but with no content inside.
Bear in mind this is my first day using Qt. I need to make this work without inheriting QMainWindow because later on I need to put this on a QMainWindow.
You're missing a top level layout:
Controls::Controls()
{
... (yoour code)
QVBoxLayout* topLevel = new QVBoxLayout(this);
topLevel->addWidget( frame );
}
Or, if frame is not used anywhere else, directly:
Controls::Controls()
{
layout = new QVBoxLayout(this);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
Note that setLayout is done automatically when QLayout is created (using parent widget)
You'll want to set a layout on your Controls class for managing its child sizes. I'd recommend removing your frame widget.
controls.cpp
Controls::Controls()
{
layout = new QVBoxLayout(this);
.
.
.
}
main.cpp
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
I was trying to add a QWidget while runtime in Qt but It is showing SIGSEV signal received from OS because of segmentation fault.
Here is my code:
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_submit_clicked();
private:
Ui::MainWindow *ui;
QLabel *label;
QLineEdit *line_edit;
};
#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_submit_clicked()
{
QString str = ui->lineEdit1->text();
QString str1 =ui->lineEdit2->text();
if(str=="rana"&&str1=="vivek")
{
label = new QLabel();
label->setText("Success");
MainWindow.layout->addWidget(label);
label->show();
}
else
{
line_edit = new QLineEdit();
line_edit->setText("Sorry");
MainWindow.layout->addWidget(line_edit);
line_edit->show();
}
}
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I know that segmentation fault occurs due to dereferencing of a null pointer but i couldn't find where I have done that mistake.Any Suggestions?
MainWindow.layout->addWidget(label);
doesn't make a lot of sense - this should not even compile, as Sebastian noted.
First, make sure you have layout in the Ui file (I added one vertical layout named verticalLayout), so you have a layout where you will add widgets. You will have a pointer to it inside your ui object.
Now, just use addWidget on that layout and everything should work:
void MainWindow::on_pushButton_submit_clicked()
{
QString str = ui->lineEdit1->text();
QString str1 =ui->lineEdit2->text();
if(str=="rana"&&str1=="vivek")
{
QLabel *label = new QLabel();
label->setText("Success");
ui->verticalLayout->addWidget(label);
// label->show(); widgets will became the part of the MainWindow, as the addWidget
// will add them into the hierarchy.
}
else
{
QLineEdit *line_edit = new QLineEdit();
line_edit->setText("Sorry");
ui->verticalLayout->addWidget(line_edit);
// line_edit->show()
}
}
Note - addWidget will set the owner of the widget to be the layout, so the widget will be deleted on the destruction of the layout.
Maybe implementing in this way will make sense?
void MainWindow::on_pushButton_submit_clicked()
{
QString str = ui->lineEdit1->text();
QString str1 =ui->lineEdit2->text();
QWidget *w = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout; // creates a vertical layout
if(str=="rana"&&str1=="vivek")
{
label = new QLabel(w);
label->setText("Success");
layout->addWidget(label);
}
else
{
line_edit = new QLineEdit(w);
line_edit->setText("Sorry");
layout->addWidget(line_edit);
}
w->setLayout(layout);
setCentralWidget(w);
}
UPDATE:
QMainWindow already has a predefined layout, so it was needless to introduce a new one. The code above creates an intermediate widget and construct it using its own layout. Than the widget set as a central widget in the MainWindow.
I have the following minimal example code given.
main.cpp:
#include <QApplication>
#include "qt.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyDialog mainWin;
mainWin.show();
return app.exec();
}
qt.cpp:
#include <QLabel>
#include "qt.h"
void MyDialog::setupUi()
{
setCentralWidget(new QWidget);
mainLayout = new QVBoxLayout( centralWidget() );
centralWidget()->setLayout(mainLayout);
// show the add new effect channel button
QPushButton* newKnobBtn = new QPushButton("new", this );
connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );
containerWidget = new QWidget(this);
scrollArea = new QScrollArea(containerWidget);
mainLayout->addWidget(containerWidget);
scrollLayout = new QVBoxLayout(scrollArea);
scrollArea->setLayout(scrollLayout);
/*
QSizePolicy pol;
pol.setVerticalPolicy(QSizePolicy::Expanding);
setSizePolicy(pol);
*/
addNewKnob(); // to fit size initially
}
void MyDialog::addNewKnob()
{
scrollLayout->addWidget(new QLabel("Hello World", this));
/*
containerWidget->adjustSize();
adjustSize();
*/
}
qt.h:
#include <QMainWindow>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QPushButton>
class MyDialog : public QMainWindow
{
Q_OBJECT
private slots:
void addNewKnob();
private:
void setupUi();
QVBoxLayout* mainLayout;
QScrollArea* scrollArea;
QVBoxLayout* scrollLayout;
QWidget* containerWidget;
public:
MyDialog( ) { setupUi(); }
};
Compiling: Put all in one directory, type
qmake -project && qmake && make
I have the adjustSize() solution from here, but it does not work: (link). Everything I commented out was things I tried but did not help.
How do I make containerWidget and scrollLayout grow correctly, when a new Label is being added to scrollLayout?
Here's a simplified version that works for me:
qt.cpp:
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include "qt.h"
MyDialog::MyDialog()
{
QWidget * mainWidget = new QWidget;
QBoxLayout * mainLayout = new QVBoxLayout(mainWidget);
setCentralWidget(mainWidget);
// show the add new effect channel button
QPushButton* newKnobBtn = new QPushButton("new");
connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );
QScrollArea * scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
mainLayout->addWidget(scrollArea);
QWidget * labelsWidget = new QWidget;
labelsLayout = new QVBoxLayout(labelsWidget);
scrollArea->setWidget(labelsWidget);
addNewKnob(); // to fit size initially
}
void MyDialog::addNewKnob()
{
labelsLayout->addWidget(new QLabel("Hello World"));
}
qt.h:
#include <QMainWindow>
#include <QBoxLayout>
class MyDialog : public QMainWindow
{
Q_OBJECT
public:
MyDialog( );
private slots:
void addNewKnob();
private:
QBoxLayout * labelsLayout;
};
You have containerWidget that contain only one QScrollArea. I don't know why do you need this. But if you need this for some reason, you need to add a layout to this widget in order to make layouts work. Also do not create a layout for QScrollArea. It already have internally implemented layout. You should add scrollLayout to the scroll area's viewport() widget instead.
When you construct a layout and pass a widget to its constructor, the layout is automatically assigned to the passed widget. You should not call setLayout after that. This action will take no effect and produce console warning.
I am getting an error while trying to run this Application ... the error message is:
main.cpp(11): error: expression must have class type
int r = dialog.exec(); and I am not sure why!!!
I am using qmake to generate the make file... I have added the necessary files to the *.pro file since Dialog is inherited from QDialog I should have access to the function exec!
#include <QtGui>
#include <QDialog>
#include <QtUtil.h>
#include <Mathematics.h>
#include <Pair.h>
#include "View.h"
class QMesseageBox;
class QAction;
class QDialogButtonBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTextEdit;
class Dialog : public QDialog {
Q_OBJECT
public:
Dialog() {
QHBoxLayout *layout = new QHBoxLayout;
// prevent left vertical box from growing when main window resized
layout->addStretch(1);
QLabel* lab_Layers = new QLabel(tr("Layers"));
d_inline = new QLineEdit;
d_inline->setText("50");
scene = new QGraphicsScene(0, 0, 500, 500);
view = new View;
layout->addWidget(view);
view->setScene(scene);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(layout);
setLayout(mainLayout);
setWindowTitle(tr("VI Smooth 0.4"));
}
private slots:
// scroll the "after" window when "before" one is scrolled (so they
// remain in sync)
private:
QAction* exitAction;
QtUtil qt;
QLineEdit* d_inline;
QGraphicsScene* scene;
QGraphicsView* view;
};
main class
#include <QApplication>
#include <QMessageBox>
#include "Dialog.h"
int
main(int argc, char **argv) {
QApplication app(argc, argv);
argv++;
Dialog dialog();
// dialog.showMaximized();
int r = dialog.exec();
return 0;
}
It should look something like this. If you create a Dialog object, you need to call show(). And you also need to return app.exec() in main().
#include <QApplication>
#include <QMessageBox>
#include "Dialog.h"
int
main(int argc, char **argv) {
QApplication app(argc, argv);
argv++;
Dialog dialog;
dialog.show()
return app.exec(argc, argv);
}