How to delete a widget - c++

Actually im having 2 Qwidgets say "Widget" , "NewWidget". I'm calling "NewWidget" in "Widget" keypress event and viced versa,
void Widget::keyPressEvent(QKeyEvent *qv)
{
// i want to delete "Widget" here before i call "NewWidget"
NewWidget *newWidget = new NewWidget();
newWidget->setStyleSheet("background-color:black;");
newWidget->setGeometry(0,0,640,480);
newWidget->show();
}
I want to delete or destroy the "Widget" before calling "NewWidget"

Try the following
this->deleteLater();
It will attempt to destroy the widget when the function exits.
It sounds dangerous/bad to destroy the current widget when you are busy inside a member function of the widget that you want to destroy. Try the above code but otherwise think about redesigning your interactions.

Related

memleak in cpp while precommit

Hi Iam working on a cocos2dx framework with cpp. I am facing memleak on a function where I use new keyword to initialize a class. Here I have a base class for all the popup in my game. I would like to make a popup from the base popup class inheriting from it. And adding the new popup as a child of a scene. The problem is when I initialize the new popup class on the stack, I couldnot call other functions which is in the new popup class. So i initialized my new popup class in heap using new keyword. Iam also deleting the instance on a function called close popup. I also saw that when clearing Iam calling the delete on the correct pointer. But my precommit says thats a memeleak. Can someone sugeest ideas? Here's my code
# Newpopup.cpp extends BasePopup
views::BasePopup* NewPopup::createPopup() {
popup = BasePopup::createPopup(Size(400, 500));
return popup;
}
void NewPopup::cleanPopup() {
popup->removeFromParent();
delete this;
}
Adding the new popup to a scene in another Scene class
# Adding to scene
void MainScene::getNewPopup() {
NewPopup* NewPopup = new NewPopup();
this->addChild(NewPopup);
}
Here am I doing the correct delete?

Qt - How to handle memory management for dialogs?

I am running into the following issue:
Users presses "Ctrl+N" which goes into function MainWindow::newAction()
In MainWindow::newAction(), create a QDialog dlg(centralWidget()) and call dlg.exec()
While dlg is open, users pressed "Ctrl+N" again
The result is that dlg never gets deleted (it will only get deleted once centralWidget() gets deleted).
The call stack is something like this:
MainWindow::newAction ()
...
MainWindow::newAction()
I am wondering how to handle this case. I want all of the local dialog variables from the first call to newAction() to be deleted by the time we go into the function newAction() again.
You also can try something like this:
void MainWindow::newAction() {
const auto dialog = new MyDialog(centralWidget());
// When user will close the dialog it will clear itself from memory
connect(dialog, &QDialog::finished, [dialog]() {
dialog->deleteLater();
});
dialog->exec();
}
However, a good move would be to stop user from summoning more QDialogs than a single one, given that this one is a modal dialog(might be a good idea to keep this dialog pointer as a class member and check is it on screen already before calling exec() on it.
If i understood the question right, you want one dialog to be opened and want to delete it before a new dialog request comes in?
If that's the case you can do following:
In MainWindow.h declare QDialog *dlg = nullptr
In your MainWindow.cpp newAction() function you can do following:
void newAction()
{
if(dlg != nullptr)
{
dlg->close();
dlg->deleteLater();
//or
//dlg->destroy(); // this will immediately free memory
}
dlg = new QDialog(centralWidget());
...
//dlg->exec(); // This will automatically make QDialog modal.
dlg->show(); // This will not make a QDialog modal.
}
I hope this will help. Remember QDialogs when displayed with exec() they automatically behave as Modal window. show() will make it non-modal.

Deleting Pointer to widget Qt C++

I am new with Qt and i am very confused about how widgets are deleted. I was reading a video and i wanted to show up a QProgressbar while the video frames are being read and then remove this QProgressbar when the video is loaded.
I have done it with 2 different ways:
Using Pointers
QWidget* wd = new QWidget();
QProgressBar* pB = new QProgressBar(wd);
QLabel* label = new QLabel(wd);
//setting geometry and updating the label and progressbar
wd->deleteLater();
wd->hide();
this code is written inside a class and i was assuming when the destructor of this class is called, the widget will be deleted with all of it's children but that didn't happen and everytime i run this function again a new widget is created without hiding or deleting the previous one (NOTE: i have tried to delete the label and progressbar from the widget assuming that they will disappear from inside the widget but this didn't happen "delete(pB);")
Using Objects
QWidget wd;
QProgressBar pB(&wd);
QLabel label(wd);
//setting geometry and updating the label and progressbar
wd.deleteLater();
wd.hide();
When i have run the same code but using objects instead of pointers , it has run exactly as i have wanted and everytime i run the function, the old widget is destroyed and a new one is created.
NOTE: -Also when i close the main window, in case of pointers, the widget wd still exists and the program doesn't terminate until i close them manually
- In case of Objects, when i close the main window everything is closed and the program is terminated correctly.
I need someone to explain me why is this happening and how if i am having a vector of pointers to widgets to delete all pointers inside that vector without any memory leakage
In typical C++ the rule would be "write one delete for every new". An even more advanced rule would be "probably don't write new or delete and bury that in the RIAA pattern instead". Qt changes the rule in this regard because it introduces its own memory management paradigm. It's based on parent/child relationships. QWidgets that are newed can be given a parentWidget(). When the parentWidget() is destroyed, all of its children will be destroyed. Hence, in Qt it is common practice to allocate objects on the stack with new, give them a parent, and never delete the memory yourself. The rules get more complicated with QLayout and such becomes sometimes Qt objects take ownership of widgets and sometimes they don't.
In your case, you probably don't need the deleteLater call. That posts a message to Qt's internal event loop. The message says, "Delete me when you get a chance!" If you want the class to manage wd just give it a parent of this. Then the whole parent/child tree will get deleted when your class is deleted.
It's all really simple. QObject-derived classes are just like any other C++ class, with one exception: if a QObject has children, it will delete the children in its destructor. Keep in mind that QWidget is-a QObject. If you have an instance allocated usingnew`, you must delete it, or ensure that something (a smart pointer!) does.
Of course, attempting to delete something you didn't dynamically allocate is an error, thus:
If you don't dynamically allocate a QObject, don't deleteLater or delete it.
If you don't dynamically allocate a QObject's children, make sure they are gone before the object gets destructed.
Also, don't hide widgets you're about to destruct. It's pointless.
To manage widget lifetime yourself, you should use smart pointers:
class MyClass {
QScopedPointer<QWidget> m_widget;
public:
MyClass() :
widget{new QWidget};
{
auto wd = m_widget->data();
auto pb = new QProgressBar{wd};
auto label = new QLabel{wd};
}
};
When you destroy MyClass, the scoped pointer's destructor will delete the widget instance, and its QObject::~QObject destructor will delete its children.
Of course, none of this is necessary: you should simply create the objects as direct members of the class:
class MyClass {
// The order of declaration has meaning! Parents must precede children.
QWidget m_widget;
QProgressBar m_bar{&m_widget};
QLabel m_label{&m_widget};
public:
MyClass() {}
};
Normally you'd be using a layout for the child widgets:
class MyClass {
QWidget m_widget;
QVBoxLayout m_layout{&m_widget};
QProgressBar m_bar;
QLabel m_label;
public:
MyClass() {
m_layout.addWidget(&m_bar);
m_layout.addWidget(&m_label);
}
};
When you add widgets to the layout, it reparents them to the widget the layout has been set on.
The compiler-generated destructor looks as below. You can't write such code, since the compiler-generated code will double-destroy the already destroyed objects, but let's pretend you could.
MyClass::~MyClass() {
m_label.~QLabel();
m_bar.~QProgressBar();
m_layout.~QVBoxLayout();
// At this point m_widget has no children and its `~QObject()` destructor
// won't perform any child deletions.
m_widget.~QWidget();
}

valgrind issue with QDialog specified with qt designer

I'm developing a simple prototype with qt creator.
I have used designer in order to design my windows.
Say us that main window has a menu with an option called "Suspend". When this option is selected, it is called the method MainWindow::on_actionSuspend_triggered() whose simplified implementation could be resumed as follows:
void MainWindow::on_actionSuspend_triggered()
{
SuspendDialog suspend_dialog(this);
suspend_dialog.setModal(true);
auto status = suspend_dialog.exec();
return;
}
The SuspendDialog was specified with designer, it is derived from QDialog class and it is very simple (three push buttons a combo box and a spin box. This class does not allocate memory.
Now, when I run valgrind inside qtcreator for checking memory usage I get two issues of type Mismatched free() / delete / delete []. Some bizarrus is that the two issues refers the same line, which is at the end of destructor of SuspendDialog whose implementation is:
SuspendDialog::~SuspendDialog()
{
delete ui;
}
And that was automatically generated by qt designer.
My question is: is this a false positive of valgrind or am I doing some wrong?
Thanks in advance
By doing the below you are asking for trouble:
SuspendDialog suspend_dialog(this); // wrong! do not pass 'this' here
Passing pointer to 'this' in Qt implies that you pass the parent responsible for release of that widget. Or, the release will happen twice: first when the object on stack getting destroyed and next when the parent object getting destroyed.
If you execute the dialog with exec() you can still allocate the dialog widget on stack but do not pass this to it:
SuspendDialog suspend_dialog;
//
suspend_dialog.exec(); // exec() only
Or you can allocate the dialog widget in the heap and then you can pass this to it:
SuspendDialog* pSuspendDialog = new SuspendDialog(this);
//
pSuspendDialog->exec(); // or maybe show() depending on task

QWidget created in an aux method does not show/draw

I have a QWidget based class that I need to instantiate from another object.
If I create the widget in the body of its parent widget class it is all good:
new NodeWidget(rootItem, this); // this works
But when I use the aux method the widget is created, but never drawn.
rootItem->createWidget(this); // internally rootItem does the same thing as above
The method itself:
void createWidget(QWidget * target) {
if (!_ui) _ui = new NodeWidget(this, target);
...
}
The way I see it, both approaches do the same thing, but the first one works while the second one does not. The NodeWidget constructor runs, but the widget does not appear in the parent widget and the paintEvent is never called. Any ideas why?
EDIT: This is certainly odd, I noticed that the following line:
new QPushButton(this);
works when called in the constructor of the parent widget, but not when called from the mousePress event. What IS the difference?
Do you call show() for your custom widget?
If the child widget is created after it's parent is already showed the parent-child relationship can't show the child too, so you need to explicitly call show().
But when the widget is added in the constructor, the parent isn't showed yet and then when the parent is showed it automatically shows all the children that were not explicitly hidden.