Adding drop down menu to Qt GUI - error 'menubar' no declared - qt

I'm trying to create a menu in Qt following this example http://doc.qt.nokia.com/latest/mainwindows-menus.html
but I keep getting the error 'menuBar' not declared in this scope
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
In context:
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
class QLabel;
class QMenu;
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private:
void createMenus();
QLabel *createLabel(const QString &text);
QMenu *saveMenu();
};
#endif
window.cpp
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}

The menu bar is a feature of the QMainWindow class.
Because your Window class is being inherited directly from QWidget, it does not have the menuBar method, hence your error.
You need to subclass your Window class from QMainWindow rather than QWidget.

Related

QWidget background images not appearing when parent exists

I have a simple widget which uses an image as background and contains some child widgets. When I create it without a parent (as a dialogue) everything is perfect. But if I create it as a child of some other widget, I can't see the background.
Can I use QWidget::setPalette to set the background for a child widget?
If not, how would you accomplish this?
#include <QWidget>
#include <QPixmap>
#include <QPalette>
#include <QLabel>
class Panel : public QWidget
{
Q_OBJECT
public:
explicit Panel(QWidget *parent = 0) QWidget(parent)
{
bgnd_ = new QPixmap(":/path/to/image.png");
PaintBackground();
QLabel* lbl = new QLabel("SomeChild",this);
}
private:
void PaintBackground()
{
QPixmap bgnd = bgnd_->scaled(this->size(), Qt::IgnoreAspectRatio);
QPalette palette;
palette.setBrush(QPalette::Background, bgnd);
this->setPalette(palette);
}
protected:
void resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
PaintBackground();
}
private:
QPixmap* bgnd_;
};
If I create this widget as an independent object with no parent, then it will render fine. I see the background and the child widget. If I create this widget as a child of another widget, then I see the lowest-level child, but the background is empty.
#include <QMainWindow>
#include "panel.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) :
QMainWindow(parent)
{
Panel* solo = new Panel();
solo->show();
Panel* child = new Panel(this);
}
};
The above class instantiates the widget in 2 ways: solo gives me a dialogue with everything looking perfect. child lets me see Panel's child widgets, but the background is white.
Troubleshooting details
I thought this could be a bug in Qt as described here so I tried filtering out ThemeChange events by reimplementing the following in both Panel and MainWindow.
bool event(QEvent *event) override
{
if (event->type() != QEvent::ThemeChange)
{
return QWidget::event(event);
}
return true;
}
That didn't help.
Instead of painting my background with a QPalette in resizeEvent I found that the answer was to paint it with QPainter in paintEvent.
#include <QWidget>
#include <QPixmap>
#include <QPainter>
#include <QLabel>
class Panel : public QWidget
{
Q_OBJECT
public:
explicit Panel(QWidget *parent = 0) : QWidget(parent)
{
bgnd_ = new QPixmap(":/path/to/image.png");
QLabel* lbl = new QLabel("Hello",this);
}
protected:
void paintEvent( QPaintEvent* e )
{
QPainter painter( this );
painter.drawPixmap( 0, 0, bgnd_->scaled(size(), Qt::IgnoreAspectRatio));
QWidget::paintEvent( e );
}
private:
QPixmap* bgnd_;
};

How to make slot for multiple QPushButtons?

From Qvector is set the number of buttons and their names (text). After cliking on the button I need to reseave text on it and display in lineEdit.
The header file:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QWidget>
#include <QVector>
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void Buttons(QVector<QString>&);
private:
QVector<QPushButton*>button;
QString mline;
QLineEdit *line;
QVBoxLayout *layout;
QAction *Clicked;
};
#endif // DIALOG_H
The source file:
#include "dialog.h"
Dialog::Dialog(QWidget *parent): QDialog(parent)
{
this->setFixedSize(this->minimumSize());
line = new QLineEdit(this);
layout = new QVBoxLayout(this);
layout->addWidget(line);
QVector<QString>v;
v.append("a");
v.append("b");
v.append("c");
v.append("5");
v.append("45");
Buttons(v);
for(int i=0;i<button.size();i++)
layout->addWidget(button[i]);
setLayout(layout);
}
Dialog::~Dialog(){}
void Dialog::Buttons(QVector<QString>&vec)
{
if(!button.isEmpty())
button.clear();
for(int i=0; i<vec.size();i++)
{
button.append(new QPushButton(this));
button[i]->setText(vec[i]);
button[i]->show();
}
}
For it I'm not using user interface (ui), and couldn't make slots for all the buttons. How can it be done?
You can use QButtonGroup to id the buttons and consolidate the signals from all the buttons to a single slot
Example
QButtonGroup myButtongroup;
connect(&myButtonGroup,SIGNAL(buttonClicked(QAbstractButton*),this, SLOT(myButtonClicked (QAbstractButton*)));
for(int i=0; i<vec.size();i++)
{
QString buttonName = vec[i];
myButtonGroup.addButton(new QPushButton(buttonName,this),i);
//Get the button using myButtonGroup.button(i) to add to your layout
// You can add the buttons to the layout right here to elimate one more loop
layout.addWidget(myButtonGroup.button(i));
}
//Slot for button clicked
void Dialog::myButtonClicked(QAbstractButton *myButton)
{
line->setText(myButton->text());// Adding the button name to line edit
}
For more QButtonGroup signals refer the documentation
You can use signal/slot in your case. The signal/slot is related to QObject. It does not matter whether you use QT Designer or not. In your code,
for(int i=0; i<vec.size();i++)
{
button.append(new QPushButton(this));
connect(button[i], SIGNAL( clicked() ), this, SLOT(OnButtonClicked()));
button[i]->setText(vec[i]);
button[i]->show();
}
Maintain a QList of QPushButton references that you add and use "signals and slots" to register the clicked() signal of each button to a single slot. Inside the function, iterate the QList of QPushButton by comparing with QObject::sender() and identify the source.
#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
class TestWidget: public QWidget
{
Q_OBJECT
private:
QLabel *label;
QVBoxLayout *mainLayout;
QList<QPushButton*> mButtonList;
public:
TestWidget(QWidget *parent=nullptr) : QWidget(parent)
{
mainLayout = new QVBoxLayout(this);
label = new QLabel;
mainLayout->addWidget(label);
this->setLayout(mainLayout);
}
void addButton(QString buttonName)
{
QPushButton *button = new QPushButton(buttonName);
QObject::connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClicked(bool)));
mButtonList.append(button);
mainLayout->addWidget(button);
}
public slots:
void buttonClicked(bool event)
{
Q_UNUSED(event)
static_cast<QPushButton*>(QObject::sender())->setFocus();
for (int i = 0; i < mButtonList.size(); ++i)
{
if (mButtonList.at(i) == sender())
{
label->setText(QString(mButtonList.at(i)->text()));
break;
}
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestWidget wid;
wid.addButton("First Button");
wid.addButton("Second Button");
wid.addButton("Third Button");
wid.addButton("Fourth Button");
wid.show();
return a.exec();
}
#include "main.moc"
The above sample code along with *.pro file is available in github

Reparenting a Qt widget

I have a WidgetA widget, which is an owner-drawn widget. It's currently placed in QMainWindow's QVBoxLayout. After clicking a button, I'd like to "detach" WidgetA from this QVBoxLayout, insert QSplitter into this QVBoxLayout and "readd" WidgetA to this QSplitter. All this without destroying WidgetA, so it will preserve its drawing context, etc.
So, currently I have this (only one widget in a window):
I'd like to put a QSplitter between WidgetA and QMainWindow, and create a new widget, WidgetB, so I'd end up with:
Later I'd like it to split even further, so both WidgetA and WidgetB would still allow themselves to be detached and placed in a new QSplitter, so it would be possible to create f.e. this hierarchy:
And, to be complete, one more step:
I'm not very experienced in Qt, so what I'm trying to do may seem pretty obvious, but I couldn't find how to "reparent" widgets. Is this possible in Qt?
Please, see reparent example, may be it helps you:
//MyMainWindow.h
#include <QWidget>
#include <QPainter>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSplitter>
class MyWidget: public QWidget
{
public:
MyWidget(QWidget* parent, int number)
: QWidget(parent),
m_number(number)
{
}
private:
virtual void paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter p(this);
p.fillRect( rect(), Qt::red);
p.drawText( rect(), Qt::AlignCenter, QString::number(m_number) );
}
private:
int m_number;
};
class MyMainWindow: public QWidget
{
Q_OBJECT
public:
MyMainWindow()
{
setFixedSize(300, 200);
m_mainLayout = new QVBoxLayout(this);
QHBoxLayout* buttonLayout = new QHBoxLayout;
m_mainLayout->addLayout(buttonLayout);
m_button = new QPushButton("Button", this);
buttonLayout->addWidget(m_button);
connect(m_button, SIGNAL(clicked()), this, SLOT(onButtonClickedOnce()));
m_initWidget = new MyWidget(this, 1);
m_mainLayout->addWidget(m_initWidget);
}
private slots:
void onButtonClickedOnce()
{
m_button->disconnect(this);
m_mainLayout->removeWidget(m_initWidget);
QSplitter* splitter = new QSplitter(Qt::Horizontal, this);
m_mainLayout->addWidget(splitter);
splitter->addWidget(m_initWidget);
MyWidget* newWidget = new MyWidget(splitter, 2);
splitter->addWidget(newWidget);
}
private:
QVBoxLayout* m_mainLayout;
QWidget* m_initWidget;
QPushButton* m_button;
};
//main.cpp
#include <QtWidgets/QApplication>
#include "MyMainWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyMainWindow mainWindow;
mainWindow.show();
return a.exec();
}
When you operate with widget which is part of layout, then you need to use appropriate methods of QLayout (parent of QVBoxLayout) to detach the item from layout:
QLayout::removeWidget (removeItem if it is not widget, but spacer item or another layout)
QLayout::addWidget (addItem --/--)
Btw: even when widget moves between layouts, its parent may even stay same. I guess you have no need to call QWidget::setParent() as the calls of addWidget/removeWidget will do all work for you.

Convert QStackedLayout to QHBoxLayout dynamically

I would like to change my widget layout from QStackedLayout to QHBoxLayout to QVBoxLayout dynamically by clicking on push buttons. I am able to switch from QVBoxLayout to QHBoxLayout and vice versa, but my approach does not work for QStackedLayout. I've exhausted all options I can think of. A sample code is attached. Does anyone know how I can achieve my objective?
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QGridLayout>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QPushButton *button1_;
QPushButton *button2_;
QPushButton *button3_;
QHBoxLayout *hLayout_;
QVBoxLayout *vLayout_;
QStackedLayout *sLayout_;
QVBoxLayout *gLayout_;
public slots:
void layoutHorizontal();
void layoutVertical();
void layoutStacked();
private:
bool isStackedLayout_;
QLabel *bar_;
};
#endif // WIDGET_H
#include "widget.h"
#include <QtAlgorithms>
#include <QDebug>
Widget::Widget(QWidget *parent) : QWidget(parent){
bar_ = new QLabel(tr("TEST!"));
button1_ = new QPushButton(tr("to Horizontal Layout"),(bar_));
button2_ = new QPushButton(tr("to Vertical Layout"),(bar_));
button3_ = new QPushButton(tr("to Stacked Layout"),(bar_));
button1_->setStyleSheet("background: rgba(255,255,0,255);");
button2_->setStyleSheet("background: rgba(255,0,255,255);");
button3_->setStyleSheet("background: rgba(0,255,255,255);");
connect(button1_,SIGNAL(clicked()),this,SLOT(layoutHorizontal()));
connect(button2_,SIGNAL(clicked()),this,SLOT(layoutVertical()));
connect(button3_,SIGNAL(clicked()),this,SLOT(layoutStacked()));
gLayout_ = new QVBoxLayout;
setLayout(gLayout_);
hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
gLayout_->addWidget(bar_);
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
resize(480,200);
}
Widget::~Widget() { }
void Widget::layoutHorizontal(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QHBoxLayout *hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutVertical(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QVBoxLayout *vLayout_ = new QVBoxLayout(bar_);
vLayout_->setObjectName(tr("currentLayout"));
vLayout_->addWidget(button1_);
vLayout_->addWidget(button2_);
vLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutStacked(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QStackedLayout *sLayout_ = new QStackedLayout(bar_);
sLayout_->setObjectName(tr("currentLayout"));
sLayout_->addWidget(button1_);
sLayout_->addWidget(button2_);
sLayout_->addWidget(button3_);
isStackedLayout_ = true;
}
The visibility property on your buttons gets set to "invisible" after pulling widgets out of the QStackedLayout (likely because the QStackedLayout relies on this property to emulate stacking). As such, I was able to get your code to work by adding the following:
void Widget::layoutHorizontal() {
...
button1_->setVisible(true);
button2_->setVisible(true);
button3_->setVisible(true);
isStackedLayout_ = false;
}
It's also worth noting that removing the widgets from the layout prior to deleting it is not necessary. The layout doesn't take ownership of the widgets in it. As such you can delete the following:
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
Create another widget with only widgets and one layout inside. Then use setLayout for your widget. Sorry for my bad C++ knowledge :)
class ChangeableWidget: public QWidget {
private QVBoxLayout vbox;
private QHBoxLayout hbox;
private QStackedLayout stacked;
private QPushButton button1;
private QPushButton button2;
ChangeableWidget()
{
button1 = new QPushButton("1");
button2 = new QPushButton("2");
vbox = new QVBoxLayout();
vbox.addWidget(button1);
vbox.addWidget(button2);
hbox = new QHBoxLayout();
hbox.addWidget(button1);
hbox.addWidget(button2);
stacked = new QStackedLayout();
stacked.addWidget(button1);
stacked.addWidget(button2);
setLayout(vbox);
}
void ChangeableWidget::layoutVertical()
{
setLayout(vbox);
}
void ChangeableWidget::layoutHorizontal()
{
setLayout(hbox);
}
}

Exit Application in Qt

I have built an app in Qt that contains two buttons: an exit button and an import button. When the import button is pushed, a list of buttons is shown in a scrollarea on the screen (the file loggers.csv contains the data 1;2;3;4;5;).
It all works fine, but when I push the exit button (which of course should close everything), the app is not stopped properly (the stop button of Qt is still active, and the play button isn't). When I run the debugger and push the exit button it gives an error: Invalid address specified to RtlFreeHeap( 0ADF0000, 0028FE40 ). Can anybody help me?
main
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.showFullScreen();
return a.exec();
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
#include "logger.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QPushButton exit_btn;
QPushButton import_btn;
private slots:
void createMenus();
void exit();
void import();
private:
int window_width;
int window_height;
int numLoggers;
int numSelected;
QVector<Logger*> loggers;
QScrollArea * scroll_area;
QVBoxLayout scrollLayout;
QWidget viewport;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QtGui"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
window_width = QApplication::desktop()->width();
window_height = QApplication::desktop()->height();
createMenus();
connect(&exit_btn,SIGNAL(clicked()),this,SLOT(exit()));
connect(&import_btn,SIGNAL(clicked()),this,SLOT(import()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createMenus()
{
import_btn.setParent(ui->centralWidget);
import_btn.setGeometry(400,300,100,100);
import_btn.setText("IMPORT");
exit_btn.setText("EXIT");
exit_btn.setParent(ui->centralWidget);
exit_btn.setGeometry(window_width-50,12,32,32);
viewport.setLayout(&scrollLayout);
viewport.resize(0,0);
scroll_area = new QScrollArea(ui->centralWidget);
scroll_area->setGeometry(0,66,317,window_height-116);
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setWidget(&viewport);
scroll_area->setGeometry(0,97,317,window_height-228);
scrollLayout.setMargin(0);
scrollLayout.setSpacing(0);
}
void MainWindow::exit()
{
close();
qApp->quit();
}
void MainWindow::import()
{
numSelected=0;
QFile f("Loggers3.csv");
if (f.open(QIODevice::ReadOnly))
{
numLoggers=0;
QString data;
data = f.readAll();
QStringList vals = data.split(';');
while(vals.size()>=1)
{
Logger * logger = new Logger;
logger->setNumber(vals[0].toInt());
vals.removeAt(0);
loggers<<logger;
numLoggers++;
}
f.close();
for(int i=0; i<numLoggers;i++)
{
loggers[i]->createButtons();
scrollLayout.addWidget(loggers[i]->button);
}
viewport.resize(367,numLoggers*60);
}
}
logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <QtGui>
class Logger : public QWidget
{
Q_OBJECT
public:
explicit Logger(QWidget *parent = 0);
~Logger();
int number;
QLabel num;
QToolButton * button;
bool checked;
signals:
public slots:
void setNumber(int number);
void createButtons();
};
#endif // LOGGER_H
logger.cpp
#include "logger.h"
#include <QtGui>
Logger::Logger(QWidget *parent) :
QWidget(parent)
{
button = new QToolButton;
button->setCheckable(true);
button->setMinimumSize(317,60);
button->setStyleSheet("QToolButton{background-image: url(images/btn_bg); border:none}");
}
Logger::~Logger()
{
}
void Logger::setNumber(int logNumber)
{
number=logNumber;
}
void Logger::createButtons()
{
QLayout * layout = new QHBoxLayout;
QSpacerItem *spacer = new QSpacerItem(120, 31, QSizePolicy::Maximum, SizePolicy::Maximum);
num.setStyleSheet("color: white; font: bold 16px");
num.setText(QString::number(number));
layout->addWidget(&num);
layout->addItem(spacer);
button->setLayout(layout);
}
I'm not entirely certain about what you are trying to achieve... but your problem lies with these two lines:
viewport.setLayout(&scrollLayout);
viewport.resize(0,0);
In the documentation for the QWidget class it states that:
If there already is a layout manager installed on this widget, QWidget
won't let you install another. You must first delete the existing layout manager (returned by layout()) before you can call setLayout() with the new layout.
This is where your problem lies. Don't believe me, add this check before those two lines of code.
if(layout()){
qDebug() << "Another layout exists";
}
Source: QVBoxLayout Class Reference
The QVBoxLayout class lines up widgets vertically.
This class is used to construct vertical box layout objects. See QBoxLayout for details.
The simplest use of the class is like this:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->show();
First, we create the widgets we want in the layout. Then, we create the QVBoxLayout object and add the widgets into the layout. Finally, we call QWidget::setLayout() to install the QVBoxLayout object onto the widget. At that point, the widgets in the layout are reparented to have window as their parent.
Critical source of error in your project:
Widgets should be constructed on the heap because they will be deleted automatically when their parents are deleted. You have a custom widget class that you instantiate on the heap. The members should also go on the heap. Also, you should consider using the parent /child hierarchy in your GUI code to ensure proper memory management and proper deletion.
In my experience, if your program stops in RtlFreeHeap it is a good sign of memory corruption.
When calling
import_btn.setParent(ui->centralWidget);
centralWidget takes ownership of import_btn. That means, when centralWidget is deleted (which happens as part of delete ui;in your MainWindow's destructor), it will call delete on your member variable!
This leads to the reported memory corruption.
You need to allocate your QPushButton's dynamically, not as a plain member variable. So make them QPushButton*.
Here's how I did it from mainwindow.cpp, thanks to and this question: How to create a correct exit button in qt
QPushButton * quit_btn = new QPushButton(this);
quit_btn->setGeometry(540,440,93,27);
quit_btn->setText("Exit");
QObject::connect(quit_btn,SIGNAL(clicked()),qApp,SLOT(quit()));
Works flawlessly :D

Resources