how to add menu dynamically in Qt - qt

I want to add, submenu to a menu item dynamically. How can I achive this?
I tried like this,
I have created an Action and submenu. Then I have added the submenu to action.
But, I have connected the “triggered” signal of action. its getting crash if I click on the action..
I have also handled the “aboutToShow” signal of menu, same its also getting crash when I click on action..
Here is the sampe code.
Submenu = new QMenu(this);
connect(Submenu, SIGNAL( aboutToShow()), this, SLOT(move ()));
QAction *test = new QAction(tr("Selection"), this);
test ->setMenu(Submenu);
menubar()->addAction(test);
I want to get the notification, before the display of submenu..
additonal information:
pleas try this code, in your main window constructor.
QAction *action = new QAction("Test",this);
QAction *dummyaction = new QAction("Testing",this);
QMenu *menu = new QMenu();
menu->addAction(dummyaction);
bool val= connect(menu, SIGNAL( aboutToShow()), this, SLOT( Move()));
val= connect(menu, SIGNAL( aboutToHide()), this, SLOT(Move()));
action->setMenu(menu);
this->menuBar()->addAction(action);
if I do like this, I am able to see one submenu item. But before that Move slot should call, its not getting called.. and even before hide also the same slot should call.. its not coming..
I tried the return values of connect.. its true only… so what is wrong with my code.. please say..

Such code should work:
QMainWindow wnd;
QAction *act = wnd.menuBar()->addMenu("SomeMenu")->addMenu("someSubmenu")->addAction("someAction");
QObject::connect(act,SIGNAL(triggered()),
someObj,SLOT(actionReaction()));
I think addMenu() addAction() should work in more reliable way. This approach works for me.

I'm not sure to understand exactly what you're willing to do into your Move() slot.
But here is your own code (I removed what seemed useless to me), modified so that it is not crashing on my computer :
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QAction>
#include <QMenu>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
QMenu* menu;
QAction *dummyaction;
QMenu* m_pSubMenu;
private slots:
void Move();
};
#endif // MAINWINDOW_H
mainwindow.cpp :
#include "mainwindow.h"
#include <QMenuBar>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
m_pSubMenu = NULL;
QMenuBar* pMenuBar = new QMenuBar(this);
setMenuBar(pMenuBar);
dummyaction = new QAction("Testing",this);
menu = new QMenu("Test", this);
menu->addAction(dummyaction);
this->menuBar()->addMenu(menu);
connect(menu, SIGNAL(aboutToShow()), this, SLOT(Move()));
}
void MainWindow::Move() {
if (!m_pSubMenu) {
m_pSubMenu = new QMenu(menu);
dummyaction->setMenu(m_pSubMenu);
}
QAction* pAction = new QAction("Test", this);
m_pSubMenu->addAction(pAction);
}
I don't know exactly what you want to do into your Move() slot, but as an example, each time the Move() slot is called, a new submenu item is added.
Hope this helps.

Related

How to add a QAction to a QListWidget

I have the following code:
roslaserscandoialog.h
public:
explicit ROSLaserScanDialog(QWidget *parent = nullptr);
~ROSLaserScanDialog();
QListWidgetItem *createItemFromAction(const QAction* action);
private slots:
void on_listWidget_itemClicked(QListWidgetItem *item);
private:
Ui::ROSLaserScanDialog *ui;
QAction *mAddMsgs;
QAction *mDeleteMsgs;
roslaserscandoialog.cpp
ROSLaserScanDialog::ROSLaserScanDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ROSLaserScanDialog)
{
ui->setupUi(this);
connect(ui->listWidget,SIGNAL(on_listWidget_itemClicked(QListWidgetItem*)),this,SLOT(createItemFromAction(QListWidgetItem*)));
}
QListWidgetItem *ROSLaserScanDialog::createItemFromAction(const QAction *action)
{
Q_ASSERT( action );
QListWidgetItem *mAddMsgs = new QListWidgetItem();
mAddMsgs->setText( action->text() );
mAddMsgs->setToolTip( action->toolTip() );
mAddMsgs->setIcon( action->icon() );
// ...
return mAddMsgs;
}
void ROSLaserScanDialog::on_listWidget_itemClicked(QListWidgetItem *item)
{
mAddMsgs = new QAction(QIcon(":ros.png"), tr("Add New Message"), this);
mDeleteMsgs = new QAction(QIcon(":remove_item.png"), tr("Remove Message"), this);
}
What I have done so far:
I came across this post and also this one. Very useful as I set up my project in a very similar way, but nothing happens when I try to click on the QListWidget.
I know that in order to trigger the action I have to go to the slot called itemClicked as I did on the above code provided.
On the official documentation I was trying to apply what is advised but I don't know why nothing happens.
Please point to the right direction for solving this problem.
Look at console output, there should a warning about connect failing. If you look at your code, the reason should be pretty obvious. Consider
SLOT(createItemFromAction(QListWidgetItem*))
versus your method which isn't even a slot
QListWidgetItem *createItemFromAction(const QAction* action);
See the difference?
And then you have this slot:
void on_listWidget_itemClicked(QListWidgetItem *item);
which you are trying to use as a signal
SIGNAL(on_listWidget_itemClicked(QListWidgetItem*))
That obviously won't work.
It's a bit unclear what you want to happen when an item is clicked, but maybe you just should call createItemFromAction directly from the on_listWidget_itemClicked.
Additionally, add debug print or use breakpoint to verify that the on_listWidget_itemClicked is actually called when you click an item. If not, then you are missing connecting the relevant signal from your list view, ie. ui->setupUi(this); does not have that connect (in other words you did not do the connection in the GUI Designer).

QT push button / stop button

I have a push button that I'd like to change to a stop button when clicked. Currently the button's text says "auto fire", it runs an endless loop and it's text changes to "stop auto fire" when clicked. My problem is breaking the endless loop by clicking/pressing this button again after the text changes.
Code so far:
void Cpp_Fire::on_auto_fire_clicked()
{
while(true)
{
ui->auto_fire->setText("Stop Auto Fire");
on_manual_fire_clicked();
}
}
I tried inserting a different slot into the loop above that runs when after the button is pressed (it runs when the button is released to be precise) but I couldn't get it to work.
I know this could be done with signals/slots and a separate stop button but I'm unfamiliar with that method and I prefer the method I described.
The problem with your endless loop is that nothing else gets a chance to work.
One approach you could use is to use a QTimer with a short interval to call the on_manual_fire_clicked() method, then have the on_auto_fire_clicked() method be responsible for changing the text on the button and enabling / disabling the timer.
The ui should get enough time to respond to clicks etc if you do it that way.
edit:
For more info on using QTimer have a look at this page:
How to use QTimer
or this tutorial:
http://www.bogotobogo.com/Qt/Qt5_QTimer.php
Here's some code:
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 slots:
void on_pushButton_clicked();
void timerslot();
private:
Ui::MainWindow *ui;
QTimer* myTimer;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QTimer>
#include<QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myTimer = new QTimer(this);
myTimer->setInterval(500);
myTimer->setSingleShot(false);
connect(myTimer, SIGNAL(timeout()), this, SLOT(timerslot()));
myTimer->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::timerslot()
{
qDebug() << "timeslot";
}
void MainWindow::on_pushButton_clicked()
{
if ( this->myTimer->isActive() == true ) {
this->myTimer->stop();
ui->pushButton->setText("Start");
} else {
this->myTimer->start(500);
ui->pushButton->setText("Stop");
}
}
I hope you get the idea and can convert it to your needs.
I fully agree Michael's answer.
This will also affect the repaint! (Try to put some windows over your application, while in endless-loop: you should see repaint problems).
Don't use endless-loops, specially not within slots!
Try QTimer, or move object to a QThread.
While in such loop: Give GUI-Thread some time. You can call QCoreApplication::processEvents().. But be careful with this.
A simple (still poor) solution with QTimer could be:
(I found, Michael entered an example in his answer. - Use it.).
//have a QTimer 'timer' in the class, and a connect signal
//timer.timeout() to 'onSingleShotFired()'
void Cpp_Fire::on_auto_fire_clicked()
{
if ( ui->auto_fire->text() == "Stop Auto Fire" )
{
timer.stop();
ui->auto_fire->setText("Start Auto Fire");
}
else
{
//MSEC_AUTOFIRE_DELAY is the delay between the autofire-shots
timer.start( MSEC_AUTOFIRE_DELAY );
ui->auto_fire->setText("Stop Auto Fire");
}
}

QModelIndexList from a QTreeView giving debug assertion

In one of my projects on Qt, I have this requirement of selecting multiple items from a folder like view (tree-view), and populate the selected items in another widget. To display available items for multi-selection, I'm using a QTreeView, and populating element hierarchy like the following
m_StandardModel = new QStandardItemModel ;
QStandardItem *rootNode = m_StandardModel->invisibleRootItem();
//defining a couple of items
QStandardItem *item1 = new QStandardItem(tr("ITEM1"));
QStandardItem *item2 = new QStandardItem(tr("ITEM2"));
QStandardItem *item3 = new QStandardItem(tr("ITEM3"));
QStandardItem *item4 = new QStandardItem(tr("ITEM4"));
rootNode->appendRow(item1 );
rootNode->appendRow(item2 );
rootNode->appendRow(item3 );
rootNode->appendRow(item4 );
//register the model
ui->treeView->setModel(m_StandardModel);
ui->treeView->expandAll();
//enabling multiselection behaviour
QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);
Everything's fine till here. I'm able to display my items in tree-view and also able to multiselect items. The problem occurs when I'm trying to use these multiple selected items from tree view.
In my UI, I have connected a button's clicked() signal to my slot, which handles the iteration and manipulation of selected items. Here's the function that's being called:
//User selects a number of features listed on the left pane and clicks this button to disable them
void MainWindow::on_pushButton_2_clicked()
{
QModelIndexList selectedItems = ui->treeView->selectionModel()->selectedIndexes();
QStringList items;
foreach(QModelIndex index, selectedItems)
{
QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
if(itemModel)
{
QStandardItem* item = itemModel->itemFromIndex(index);
items<< item->data().toString();
}
}
}
Debugging till the function end is perfect. But as soon as I exit this function (shown above), I get a DEBUG ASSERTION !! like the following
HEAP[myprog.exe]: Invalid address specified to RtlValidateHeap( 00390000, 01946798 )
The call stack is showing that this assertion is reached because of destruction of local QModelIndexList that I've created in the function.
Following is the call stack at the time of debug assertion:
Any idea, what I might be missing? I have tried a number of times, but yet unable to figure out the real problem. Is there a better way of doing what is being done here?
I'm using QT 4.8.4, and am building/debugging my application in DEBUG configuration on Windows 7.
I tried your code in a Windows application and I don't see your behaviour, maybe you have extra code in other part of the program that generates that behaviour. The code I tested is the following (I only modified the way to get the data, ot get the display role item->data(Qt::DisplayRole).toString()):
The cpp file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_StandardModel = new QStandardItemModel ;
QStandardItem *rootNode = m_StandardModel->invisibleRootItem();
//defining a couple of items
QStandardItem *item1 = new QStandardItem(tr("ITEM1"));
QStandardItem *item2 = new QStandardItem(tr("ITEM2"));
QStandardItem *item3 = new QStandardItem(tr("ITEM3"));
QStandardItem *item4 = new QStandardItem(tr("ITEM4"));
rootNode->appendRow(item1 );
rootNode->appendRow(item2 );
rootNode->appendRow(item3 );
rootNode->appendRow(item4 );
//register the model
ui->treeView->setModel(m_StandardModel);
ui->treeView->expandAll();
//enabling multiselection behaviour
QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);
connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(on_pushButton_clicked()) );
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
QModelIndexList selectedItems = ui->treeView->selectionModel()->selectedIndexes();
QStringList items;
foreach(QModelIndex index, selectedItems)
{
QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
if(itemModel)
{
QStandardItem* item = itemModel->itemFromIndex(index);
items << item->data(Qt::DisplayRole).toString();
}
}
}
The header file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QStandardItemModel * m_StandardModel ;
};
#endif // MAINWINDOW_H
Maybe you can publish the hole source code to see the behaviour you are having.

showing hidden dockwidget in qt

hi i create a dockwidget which i am starting it as hidden. The problem is that afterwards i cannot show it, while i can get the status correctly from the isHidden() function. The weird thing is that if i start the dockwidget not hidden, it works perfect. I am including an example that reproduces this strange behaviour.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void showDock();
private:
Ui::MainWindow *ui;
QDockWidget *dock;
QPushButton *button;
};
#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);
// QMainWindow mainWindow;
// QDockWidget *dock = new QDockWidget(&mainWindow);
QDialog *dockDialog = new QDialog(this); // <---------edit: you need to create a parent widget for the dock
dock = new QDockWidget(dockDialog);
dock->setStyleSheet("QDockWidget { font: bold }");
dock->setFloating(true);
dock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton");
if(floatButton)
floatButton->hide();
dock->setAllowedAreas( Qt::NoDockWidgetArea );
dock->setWindowTitle("Tools");
this->addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
QMainWindow *window = new QMainWindow(dock); // <------edit: set the dock to be the parent for the window
window->setWindowFlags(Qt::Widget);
QToolBar *bar = new QToolBar(window);
bar->setMovable(false);
bar->addAction("Select");
bar->addAction("Polygon");
bar->addAction("Brush");
bar->addAction("Erazer");
bar->addSeparator();
bar->addAction("Mark");
bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
bar->setOrientation(Qt::Vertical);
window->addToolBar(Qt::LeftToolBarArea, bar);
window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
window->setParent(dock);
dock->setWidget(window);
dock->hide(); // <------------ comment this line and it will work, edit: you do not need to do that anymore, it is working nicely now
button = new QPushButton("show", this);
button->setCheckable(true);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(showDock()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showDock()
{
// qDebug() << "hello";
if(button->isChecked()){
if(dock->isHidden()){
qDebug() << "hidden";
dock->setFloating(true); // <-----edit: you need to add these lines in order to be able to see the dialog that contains the dock widget, i do not know why i need to that again since in the initialization i already specifying that my dock is floatable
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton"); // <---------edit: add this lines in order to get rid off the floating button
if(floatButton)
floatButton->hide(); // <----edit: the same as previous
dock->show();
}
}
if(!button->isChecked()){
if(!dock->isHidden()){
qDebug() << "not hidden";
dock->hide();
}
}
}
as it is now the above code the dockwidget is not appearing in the screen. If you try to comment the line that i am specifying in the mainwindow.cpp it works, but the point is that i want to start the dockwidget hidden. Does someone have any idea, of what is happening.
Thanks.
Parent of the QDock control should be your window widget, and not object of the MainWindow class.
So, you need to replace this:
dock = new QDockWidget(this);
with this:
QMainWindow *window = new QMainWindow(0); // I smell a potential leak here (set the parent!)
dock = new QDockWidget(window);
Control is visible when you press Show button in the first case, too, but it is somewhere outside the window, so you may not see it. Also, there is no need to create separate instance of QMainWindow inside class that is already inheriting QMainWindow.
I see you show()/hide() your dockwidget. I haven't tried it myself but maybe you should hide and show the dockwdiget with the QDockWidget::toggleViewAction method.

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