Qt: Can child objects be composed in their parent object? - c++

In Qt, can I embed child widgets in their parent via composition, or do I have to create them with new?
class MyWindow : public QMainWindow
{
...
private:
QPushButton myButton;
}
MyWindow::MyWindow ()
: mybutton("Do Something", this)
{
...
}
The documentation says that any object derived from QObject will automatically destroyed when its parent is destroyed; this implies a call to delete, whcih in the above example would crash.
Do I have to use the following?
QPushButton* myButton;
myButton = new QPushButton("Do Something", this);
EDIT
The answers are quite diverse, and basically boil down to three possibilities:
Yes, composition is ok. Qt can figure out how the object was allocated and only delete heap-allocated objects (How does this work?)
Yes, composition is ok, but don't specify a parent, since the parent would otherwise call delete on the object (But won't a parent-less widget turn into a top-level window?)
No, widgets always have to be heap-allocated.
Which one is correct?

The non-static, non-heap member variables are deleted when that particular object's delete sequence starts. Only when all members are deleted, will it go to the destructor of the base class. Hence QPushButton myButton member will be deleted before ~QMainWindow() is called. And from QObject documentation: "If we delete a child object before its parent, Qt will automatically remove that object from the parent's list of children". Hence no crash will occur.

Object trees & ownership answers your question. Basically when the child object is created on the heap it will be deleted by its parent.
On the other hand when the child object is created on the stack the order of destruction is important. The child will be destroyed before its parent and will remove itself from its parent's list so that its destructor is not called twice.
There is also an example in that link that shows problematic order of destruction.

The documentation says that any object derived from QObject will automatically destroyed when its parent is destroyed; this implies a call to delete
No. It implies a call to the destructor of that particular entity.
Say in your example, if MyWindow is destroyed, it means the destructor of the MyWindow has been called. Which in turn will call the destructor myButton which is implemented already in QPushButton.
If you have composite entity, just the destructor will be called on that entity but not delete and so it won't crash.
Parent child relationships in Qt doesn't require specifically to be in a stack or heap. It can be in anything.
A similar example in parent child relationship over a stack is over here.
HTH..

The object will be destroyed only when it has a parent pointer, so you can use:
MyWindow::MyWindow ()
: mybutton("Do Something", 0)
{
...
}

You should create it on heap, since QObject will destroy it :
class MyWindow : public QMainWindow
{
...
private:
QPushButton *myButton;
}
MyWindow::MyWindow ()
: mybutton( new QPushButton( "Do Something", this) )
{
...
}

calling delete operator will not crash ur application, you can read the following quote
Qt's parent–child mechanism is implemented in QObject. When we create an object (a widget, validator, or any other kind) with a parent, the parent adds the object to the list of its children. When the parent is deleted, it walks through its list of children and deletes each child. The children themselves then delete all of their children, and so on recursively until none remain. The parent–child mechanism greatly simplifies memory management, reducing the risk of memory leaks. The only objects we must call delete on are the objects we create with new and that have no parent. And if we delete a child object before its parent, Qt will automatically remove that object from the parent's list of children.
note that the parent argument is NULL by default (default argument)
this is QPushButton Constructor
QPushButton ( const QString & text, QWidget * parent = 0 )
so u can use
MyWindow::MyWindow () : mybutton( new QPushButton( "Do Something") ){ ... }
and u can call delete on any component and any time
Qt will take care for this point

Let me just quote the source here.
816 QObject::~QObject()
817 {
818 Q_D(QObject);
819 d->wasDeleted = true;
820 d->blockSig = 0; // unblock signals so we always emit destroyed()
821
...
924
925 if (!d->children.isEmpty())
926 d->deleteChildren();
927
928 qt_removeObject(this);
929
930 if (d->parent) // remove it from parent object
931 d->setParent_helper(0);
932
933 #ifdef QT_JAMBI_BUILD
934 if (d->inEventHandler) {
935 qWarning("QObject: Do not delete object, '%s', during its event handler!",
936 objectName().isNull() ? "unnamed" : qPrintable(objectName()));
937 }
938 #endif
939 }
...
1897 void QObjectPrivate::deleteChildren()
1898 {
1899 const bool reallyWasDeleted = wasDeleted;
1900 wasDeleted = true;
1901 // delete children objects
1902 // don't use qDeleteAll as the destructor of the child might
1903 // delete siblings
1904 for (int i = 0; i < children.count(); ++i) {
1905 currentChildBeingDeleted = children.at(i);
1906 children[i] = 0;
1907 delete currentChildBeingDeleted;
1908 }
1909 children.clear();
1910 currentChildBeingDeleted = 0;
1911 wasDeleted = reallyWasDeleted;
1912 }
So as you can see, QObject does indeed delete each of its children in the destructor. In addition, the destructor is executed before destructors of any members; so if the composite in question equals the parent – then member QObject won't have any chance to remove itself from the children list of its parent.
This, unfortunately, means that you cannot compose a QObject into its parent. But you can compose into other objects, as well as allocate on stack – as soon as you guarantee to destruct the object or reset its parent to 0 before the parent starts destructing.

Related

When should I use pointer or reference members, and when should I pass nullptr or this as parent pointer in Qt?

The Code
I've been writing this c++ with Qt knowing it works but not really understanding why I sometimes do things other than "I just know I should be doing this".
This is my startup class which initialises my classes:
namespace GUI
{
Startup::Startup() :
QObject(nullptr),
m_setupTab(*new SetupTab(nullptr)),
m_regTab(*new CbcRegistersTab(nullptr)),
m_dataTab(*new DataTestTab(nullptr)),
m_mainView(*new MainView(nullptr,
m_setupTab,
m_regTab,
m_dataTab)),
m_systemController(*new SystemController(nullptr,
Provider::getSettingsAsSingleton())),
m_dataTest(*new DataTest(nullptr,
m_systemController)),
m_setupTabVm(new SetupTabViewManager(this,
m_setupTab,
m_systemController,
Provider::getSettingsAsSingleton() ))
{
}
Then in my header file the member variables are described as such:
private:
SetupTab& m_setupTab;
CbcRegistersTab& m_regTab;
DataTestTab& m_dataTab;
MainView& m_mainView;
Settings* m_settings;
SystemController& m_systemController;
DataTest& m_dataTest;
SetupTabViewManager* m_setupTabVm;
The main difference between the view manager and everything else is that view manager passes signals between the tab classes and everything else.
Then to start this in my main, all I do is this:
GUI::Startup startup;
startup.show();
SetupTabViewManager.cpp:
#include "setuptabviewmanager.h"
#include "View/setuptab.h"
#include "Model/systemcontroller.h"
#include "Model/settings.h"
#include <QDebug>
namespace GUI
{
SetupTabViewManager::SetupTabViewManager(QObject *parent,
SetupTab& tab,
SystemController& sysCtrl,
Settings& config) :
QObject(parent),
m_setupTab(tab),
m_systemController(sysCtrl)
{
WireMessages(config);
WireSetupTabButtons(config);
}
void SetupTabViewManager::WireMessages(Settings& config)
{
connect(&config, SIGNAL(notifyStatusMessage(QString)), //for QT4
&m_setupTab, SLOT(onStatusUpdate(QString)) );
connect(&m_systemController, SIGNAL(notifyStatusMessage(QString)),
&m_setupTab, SLOT(onStatusUpdate(QString)));
}
void SetupTabViewManager::WireSetupTabButtons(Settings& config)
{
connect(&m_setupTab, SIGNAL(onBtnLoadSettingsClicked(bool)),
&config, SLOT(onLoadButtonClicked(bool)) );
connect(&config, SIGNAL(setHwTree(QStandardItemModel*)),
&m_setupTab, SLOT(setHwTreeView(QStandardItemModel*)));
connect(&m_setupTab, SIGNAL(onBtnInitClicked()),
&m_systemController, SLOT(startInitialiseHw()));
connect(&m_setupTab, SIGNAL(onBtnCfgClicked()),
&m_systemController, SLOT(startConfigureHw()));
}
}
Questions
What is the advantage of initialising a class in a member variable as a pointer or a reference? I just know when I make a "view manager", I should initialise the member variable as a pointer. Though I'm not sure why?
Also what is the advantage of "this" or "nullptr" as the parent to the class?
Qt objects are organized in object trees. It allows a programmer not to care about destructing the created objects: they will be deleted automatically when their respective parents are deleted.
If you take a look at almost any Qt GUI application, then you will see that all of its widgets (buttons, checkboxes, panels, etc.) have one single ancestor - the main window. When you delete the main window, all your application widgets are automatically deleted.
You can set up this parent-child relation by passing a parent object to a newly created child:
QWidget *mainWidget = ...
QPushButton *btn = new QPushButton(mainWidget);
In this case, btn object becomes a child of the mainWidget object, and from this moment you may not delete that child manually.
If you create an object without a parent, you should always delete it by yourself.
As thuga mentioned in the comments, you can transfer object ownership later. Widgets can be places inside layouts and it will make them children of the layout owner. Or you can even explicitly set parent with QObject::setParent.
And as for declaring class members as pointers or references - it does not really matter. It's just a question of convenience.
In Qt world all child objects are getting deleted when their parent object is deleting. If you do not define class members (QObjects) as pointers, they will be deleted twice: once by their parent, and second time when your class object is destructed by itself, and this can lead to undefined behavior.

C++ Qt remove all graphics: Is there a clear all graphics function [duplicate]

I am using the constructor QWidget(QWidget *parent). This parent widget contains a lot of child widgets. I need to clear all the child widgets from the parent at runtime. How can I do this?
Previous answer is wrong!! You cannot use findChildren to delete a widget's children, because Qt4's findChildren recursively lists children. Therefore, you will delete children of children, which then may be deleted twice, potentially crashing your app.
More generally, in Qt, taking a list of QObject pointers and deleting them one by one is dangerous, as destroying an object may chain-destroy other objects, due to the parent ownership mechanism, or by connecting a destroyed() signal to a deleteLater() slot. Therefore, destroying the first objects in the list may invalidate the next ones.
You need to list children widgets either by:
Passing the Qt::FindDirectChildrenOnly flag to findChild if you are using Qt5 (which did not exist when the question was asked...)
Using QLayout functions for listing items,
Using QObject::children, and for each test if it is a widget using isWidgetType() or a cast
Using findChild() in a loop and delete the result until it returns a null pointer
To take care of the recursivity problem pointed out by #galinette you can just remove the widgets in a while loop
while ( QWidget* w = findChild<QWidget*>() )
delete w;
Summarizing and supplementing:
For Qt5 in one line:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
For Qt5 for a lot of children, using setUpdatesEnabled():
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
Note that this is not exception safe! While Qt does not at this time appear to throw exceptions here, the signal destroyed() could be connected to code that does throw, or an overridden Object::childEvent(QChildEvent*) could throw.
Better would be to use a helper class:
class UpdatesEnabledHelper
{
QWidget* m_parentWidget;
public:
UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); }
~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); }
};
...
UpdatesEnabledHelper helper(parentWidget);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
For Qt4:
QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
if (widget->parentWidget() == parentWidget)
delete widget;
Removing from the QLayout works in both Qt4 and Qt5:
QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
delete child;
QObjects (and therefore QWidgets) remove themselves (automagically) from their parent in their (QObject) destructor.
From Qt docs
The following code fragment shows a safe way to remove all items from a layout:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
You can use the following in your parent widget class:
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}

How to delete object on the heap when another heap object is deleted

I have the following source code:
void Processmethod()
{
QDialog *ProcessMessage = new QDialog;
Ui::DialogProcessMessage *Dialog = new Ui::DialogProcessMessage();
Dialog->setupUi(ProcessMessage); //polymorphy
ProcessMessage->setModal(true);
ProcessMessage->setAttribute(Qt::WA_DeleteOnClose);
connect(Dialog->pushButtonAbort, SIGNAL(clicked()), &Prozess, SLOT(kill()));
connect(&Prozess6, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(helper()));
connect(&Prozess6, SIGNAL(error(QProcess::ProcessError)), this, SLOT(helper()));
connect(this,SIGNAL(enablePushButton(bool)),Dialog->pushButtonClose, SLOT(setEnabled(bool)));
Prozessmeldung->setModal(true);
ProcessMessage->show();
processmethodONE();
}
How can I delete the heap-object Dialog best when the heap-object ProcessMessage is deleted (which is deleted when closed)? Both objects must be created on the heap. Furthermore the class "Ui::DialogProcessMessage" is directly created by the ui-file and therefore any changes in it will be deleted everytime the ui-file is changed.
You need to subclass QDialog, add field in new class for your sub object assign it when creating and add destructor who will free memory of subojbects when your CustomNewSubclassedQDialog if destroyed.
All instances of QObject emit a destroyed(QObject*) signal when they are deleted. Connect ProcessMessage's signal to some other persistent object's slot, and delete your Dialog heap-object from there.
Ref.: Qt documentation for QObject
You can delete the Dialog object in ProcessMessage's destructor.
You'll have to document this to make it clear that ProcessMessage is responsible for the Dialog. Note that this doesn't seem like a good idea. The best approach here is to manually delete both objects when you're done with them. There's nothing restricting anyone from creating a Dialog in automatic storage, which when attempted to be deleted might cause undefined behavior.
Is Ui::DialogProcessMessage a class of your own? Is it derived from QObject? If so, pass the ProcessMessage pointer to the Dialog constructor as its parent. That way ProcessMessage becomes responsible for deleting Dialog. I.e. your declaration of the Ui::DialogProcessMessage class should look something like this:
namespace Ui
{
class DialogProcessMessage: public QDialog
{
Q_OBJECT
public:
DialogProcessMessage(QObject* parent=0) :
QDialog(parent)
{ /* ... */ }
/*
* more stuff ...
*/
};
}
And then, construct Dialog as follows:
Ui::DialogProcessMessage *Dialog = new Ui::DialogProcessMessage(ProcessMessage);
You might want to refer to the Qt documentation for more information.

How do I share objects between a closed QDialog and newly opened QMainWindow?

I have an application that opens a QDialog for some flow, and when it is closed, the QMainWindow is opened.
In the QDialog I create some objects that I'd like to pass as a pointer (or some other way) to the QMainWindow. For example I create a SysTray object that needs to change its state from the QMainWindow. What is the best way? Singletons?
update .
after implementing the sulotion another question was rises , does the QDialog is cleaned from memory that means , invoked its destructor ? i don't think its the case . i have to do some object cleaning , and there destructor never invoked
One approach is to allocate on the heap with the QMainWindow as a parent. The QObject-hierarchy will take care of freeing the memory and you will access the object for the lifetime of the QMainWindow.
If at any point you know for sure that you don't need the QDialog or the shared object anymore, you can call deleteLater.
Example:
class MyDialog : public QDialog
{
Q_OBJECT
QObject* _objToShare;
public:
QObject* objToShare() const { return _objToShare; }
MyDialog(QObject* parent = 0) : QDialog(parent)
{
_objToShare = new QObject(this); // either use this as the parent
// or free by hand in the destructor
}
// ...
};
class MyWindow : public QMainWindow
{
Q_OBJECT
// ...
QObject* ptrToSharedObj; // alternatively you can hold a pointer
// to your MyDialog instance
};
Where you use your QDialog:
MyDialog* d = new MyDialog(this);
d->exec();
ptrToSharedObj = d->objToShare();
// don't delete d explicitly, the QObject hierarchy will take care of that
A better (and likely more memory-friendly) approach is to use a shared pointer implementation. Qt has a variety of smart pointer classes, one of which is QSharedPointer. It is basically a thread-safe, reference-counted pointer which means that if you grab one that points to the shared object of your QDialog, it will not get freed as long as there are any other QSharedPointers pointing to it. Keep in mind that this might cause circular references if you are not careful.
Example:
class MyDialog : public QDialog
{
Q_OBJECT
QSharedPointer<QObject> _objToShare;
// ^ don't delete in the destructor
public:
QSharedPointer<QObject> objToShare() const { return _objToShare; }
MyDialog(QObject* parent = 0) : QDialog(parent)
{
_objToShare = QSharedPointer<QObject>(new QObject);
// no parent to avoid destruction when the dialog is destructed
}
// ...
};
class MyWindow : public QMainWindow
{
Q_OBJECT
// ...
QSharedPointer<QObject> ptrToSharedObj;
};
Where you use your QDialog:
MyDialog d;
d.exec();
ptrToSharedObj = d.objToShare();
From this point on, even if d goes out of scope (i.e. destroyed), you will still have a valid pointer to the shared data (well, of course unless you do something explicitly to invalidate it).
You have a lot of different options. Some of these may not be applicable to your situation:
Case 1: Caller knows best (i.e. procedural programming)
Define a controller that can control the ordering. That control can then act as the intermediary and get the data once the dialog has closed:
void FlowController::displayFlow()
{
MyDialog *dialog = new MyDialog();
YourSharedData *data = NULL;
int result = dialog->exec();
if (result == QDialog::Accepted) {
data = dialog->sharedDataAccessor();
}
MyMainWindow *window = new MyMainWindow();
window->setSharedData(data);
window->exec();
}
Case 2: Message Passing
Create both the dialog and the main window up front. Connect the corresponding signals and slots and let them both be ignorant of one another. This is usually much easier to test and keep decoupled:
void AppLauncher::launch()
{
MyDialog *dialog = new MyDialog();
MyMainWindow *window = new MyMainWindow();
window->connect(
dialog,
SIGNAL(dialogResult(int, const SharedData&)),
SLOT(setDialogResult(int,const SharedData&))
);
}
void MyMainWindow::setDialogResult(int result, const SharedData& sharedData)
{
if (result == Dialog::Accepted) // something domain-specific would be better
{
this->processSharedData(sharedData); // do whatever with it.
}
}
Case 3: Shared State Dependency
Define your shared data up front and make it a dependency for each form. Each form then defines state, acts based on that state, or some combination of both:
void AppLauncher::launch()
{
SharedData *data = this->createSharedData();
MyDialog *dialog = new MyDialog(data);
MyMainWindow *window = new MyMainWindow();
dialog->exec(); // does what it needs with shared data
window->exec(); // checks shared data and acts accordingly
}
Case 4: MVC / MVP / MVVM
You may be able to define your shared state as a model that they both act upon. This may not be much different than case three above.
Case 4: Singleton or global state
It will work, but please don't do it :).
In QDialog you have owner, which is probably QMainWindow. (if not, you may add it there, ore get parent objects until you come to QMainWindow class). You may refer to it when creating new objects...
You can subclass QApplication to have it keep a pointer to your systray object, or other objects which should be available "application wide".
In a Qt application, there is only a single instance of QApplication, available everywhere using the qApp macro.
See this mailing list discussion which also contains an example.

destructors in Qt4

I'm very confused about using destructors in Qt4 and hope, you guys can help me.
When I have a method like this (with "Des" is a class):
void Widget::create() {
Des *test = new Des;
test->show();
}
how can I make sure that this widget is going to be deleted after it was closed?
And in class "Des" i have this:
Des::Des()
{
QPushButton *push = new QPushButton("neu");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(push);
setLayout(layout);
}
where and how do I have to delete *push and *layout? what should be in the destructor Des::~Des() ?
Qt uses what they call object trees and it's a bit different from the typical RAII approach.
The QObject class constructor takes a pointer to a parent QObject. When that parent QObject is destructed, its children will be destroyed as well. This is a pretty prevalent pattern throughout Qt's classes and you'll notice a lot of constructors accept a *parent parameter.
If you look at some of the Qt example programs you'll find that they actually construct most Qt objects on the heap and take advantage of this object tree to handle destruction. I personally found this strategy useful as well, as GUI objects can have peculiar lifetimes.
Qt provides no additional guarantees beyond standard C++ if you're not using QObject or a subclass of QObject (such as QWidget).
In your particular example there's no guarantee that anything gets deleted.
You'll want something like this for Des (assuming Des is a subclass of QWidget):
class Des : public QWidget
{
Q_OBJECT
public:
Des(QWidget* parent)
: QWidget(parent)
{
QPushButton* push = new QPushButton("neu");
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(push); // this re-parents push so layout
// is the parent of push
setLayout(layout);
}
~Des()
{
// empty, since when Des is destroyed, all its children (in Qt terms)
// will be destroyed as well
}
}
And you'd use class Des like so:
int someFunction()
{
// on the heap
Des* test = new Des(parent); // where parent is a QWidget*
test->show();
...
// test will be destroyed when its parent is destroyed
// or on the stack
Des foo(0);
foo.show();
...
// foo will fall out of scope and get deleted
}
Another option to using deleteLater(), or parents, is to use the delete-on-close functionality for widgets. In this case, Qt will delete the widget when it is done being displayed.
Des *test = new Des;
test->setAttribute( Qt::WA_DeleteOnClose );
test->show();
I like to use it with the object tree that Qt keeps, so that I set delete-on-close for the window, and all widgets in the window have a proper parent specified, so they all get deleted as well.
Richardwb's answer is a good one - but the other approach is to use the deleteLater slot, like so:
Des *test = new Des;
test->show();
connect(test, SIGNAL(closed()), test, SLOT(deleteLater()));
Obviously the closed() signal can be replaced with whatever signal you want.
This tutorial suggests you don't need to explicitly delete widgets that have been added to parent widgets. It also says it doesn't hurt to do delete them either.
(I've not tested this, but I guess as long as you explicitly delete them before the parent widget is deleted, this should be OK.)
In most cases you should create widgets on the stack:
QPushButton push("neu");
This way, they get deleted when they become out of scope. If you really want to create them on the heap, then it's your responsibility to call delete on them when they are not needed anymore.