What is the purpose of QWidget's parent? - c++

If I subclassed any widget the usual pattern is:
ZTabWidget::ZTabWidget(QWidget *parent):QTabWidget(parent){
blah ... blah ...
}
The usual pattern is:
WidgetB widgetb = new WidgetB(widgeta)
widgeta.addWidget(widgetb);
Is there any harm in having all my widgets assigned MainWindow as their respective parent - even though, following the trails of addWidget hierarchy, most of those widgets have another widget as the addWidget parent:
WidgetB widgetb = new WidgetB(mainWindow)
widgeta.addWidget(widgetb);
The reason I wish to do this is because mainWindow holds all the main items of the application and that I could have my any of my subclassed widgets reference those items.
In fact, I am thinking of a proxy widget that is merely used to hold some common references and use that proxy widget as the common parent of all my widgets. Any problem in that?
Exactly, what is the use of having registered a parent for a QWidget? Is the parent even used internally?
Does the addWidget parent have to be the same as the constructor parent?

There are actually two aspects two your questions:
Memory management
The tree-like organization of QWidgets (and in fact of any QObjects) is part of the memory management strategy used within the Qt-Framework. Assigning a QObject to a parent means that ownership of the child object is transferred to the parent object. If the parent is deleted, all its children are also deleted. From the docs:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor. You can look for an object by name and optionally type
using findChild() or findChildren().
This means you can organize your widgets in any way that seems sensible to you (as long as you don't introduce memory leaks). I think, however, that it is a common practice to assign all the widgets to their respective container (either explicitly, or better, using methods like addWidget).
If a widget is assigned to a QLayout using addWidget, then ownership of the widget is transferred to the layout (which in turn is probably owned by another surrounding layout or the main window). So yes, the relationship defined by this method includes the more general parent-child relationship described above.
Now, as soon as the main window gets destroyed, basically the whole tree of QObjects is deleted as you'd expect.
Consequently, if you leave an object "parentless", it is your own responsibility to delete it.
GUI semantics
As Frank noted correctly, in some contexts the parent-child relationship between QWidgets also bears a semantically meaning to the GUI framework. An example of this are modal dialogs, who block their parent as long as they stay open.

Related

Qt5 QMainWindow components deletion

One of our teacher asked us to create a Qt application without any UI file for the main window (a QMainWindow). Usually I always create one, leave it empty and let the uic deal with it.
I know that if a parental relation is defined between a widget (child) and its parent, then there is no need to delete the widget (deleted when the parent is deleted). So, when the UI is deleted, all the children are destroyed.
If we do not use an UI file (not generated), do we have to manually delete all the widget added to the GUI?
A little sample:
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent){
layout = new QHBoxLayout(this);
aButton = new QButton(this);
layout->addWidget(aButton);
...
}
MainWindow::~MainWindow(){
delete ui; // No need to delete more if parental relation.
// However, what do we do if no ui has been generated?
// Do we have to delete aButton?
}
The value of parent is 0. It is the main entry of the application.
Thanks
Please refer to this article
QWidget, the fundamental class of the Qt Widgets module, extends the parent-child relationship. A child normally also becomes a child widget, i.e. it is displayed in its parent's coordinate system and is graphically clipped by its parent's boundaries. For example, when the application deletes a message box after it has been closed, the message box's buttons and label are also deleted, just as we'd want, because the buttons and label are children of the message box.
So, there is no difference do you use ui or not. When you delete window, all its children will be deleted too.

Using UI design files and having a custom widget with custom constructor QT

I have 2 custom widgets inheriting from QGLWidget and I aim to show the same scene from 2 different views using these widgets. For this I share the first widget with the second widget. However this requires a custom constructor than the compiled UI file provides.
Such as
// The line I mention from Compiled UI file
widget_2 = new SideGlWidget(widget);
// What I actually want this line to be
widget_2 = new SideGlWidget(widget, MainScreen);
Some suggests to set such additional parameters later using an init function. Then how do I set shareWidget member of QGLWidget?
here is the contructor of SideGlWidget
SideGlWidget::SideGlWidget(QWidget *parent,QGLWidget * shareWidget)
: QGLWidget(parent,shareWidget)
{
}
Any comments and edits are welcome.
When dealing with Qt widgets generated through a UI file, you can't change how the constructor of your custom widget is called.
You have two options then :
Make a default second parameter to the SideGlWidget
Add a init( sharedWidget) method to your widget and call it after setupUi() (most likely in your main window's constructor). You can thus pass your parameter to the side widget before it is shown.
This forum post explains it in detail.
Looking at your problem at a higher level, I would suggest using some kind of shared object that holds common data to the two widgets and use either inheritance or composition instead of defining one widget to use another.
Here is the official and latest solution to this problem from http://doc.qt.io/qt-5/qopenglwidget.html:
When multiple QOpenGLWidgets are added as children to the same
top-level widget, their contexts will share with each other. This does
not apply for QOpenGLWidget instances that belong to different
windows.
Therefore by inheriting from QOpenglWidget instead of QGlWidget you dont have to deal with context sharing at all. Beware that updategl function is replaced with update function.

StandardItemModel Qt

QStandardItemModel::​QStandardItemModel(QObject * parent = 0)
Constructs a new item model with the given parent.
I thought models can share multiple views then why we are passing a widget to QStandardItemModel Constructor?
Actually QObject is not a widget, so that model is not dependent on any GUI component. The QObject argument passed to constructor because QStandardItemModel is a QObject itself and it follows Qt's standard parent-child relationship in QObjects hierarchy. If you want your model instance get deleted when its parent object destroyed, pass its pointer to the model's constructor.

Setting common parent Qt widget for new widget in separate thread

I need to create a widget in a separate thread and to set MainWindow for it as a parent widget. Creation of a thread cannot be avoided.
In the constructor of a new widget I am specifying a pointer to MainWindow, but give
QObject::setParent: Cannot set parent, new parent is in a different thread
How to solve this?
P.S. Child widgets may be numerous.
You cannot create UI widgets outside of main thread
This is not possible. See the following code reference for details why not:
QObject source code
In particular, you would need to pay attention to this warning:
"qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");"
which you got on the command line based on your question, so this is all expected.
As the warning says, you need to make sure that the parenting happens in the same thread between the parent and child.
Creation of a thread cannot be avoided. How to solve this?
I am afraid you will need to refactor the code by either moveing this out of your thread into the same where the parent is or/and not have the separate thread at all.
Based on the information in your question, currently, it is not possible to say more since we do not yet completely know the functionality of your other thread.
Hope this helps with explaining it.

How to structure signals/slots?

I am creating a UI with Qt and there are two elements which may or may not be present. Additionally, their parents are different elements as well. However, one affects the other.
How should I structure the signals/slots (or should I not even use that pattern) in the best way?
The methods that come to mind all seem like hacks:
create a signal/slot in all parents and pass up and then back down the signal
create a signal/slot in the closest common parent of both then have the children connect their signals/slots to the parents'
on creation of one navigate the structure of the other to get the element and then connect signals/slots directly. Any guidance here is greatly appreciated.
Edit: "present" means that there is a button that the user may press that creates an element and adds it to the layout. So depending on the combination of button presses, an element may be present or not.
"affect" means it changes its state. for example, there is a list of items and a button elsewhere which adds an element to the list.
For an example, imagine a tabbed pane which contains a todo list. There is a button not in the tabbed pane which adds an item to the list. The tabbed pane does NOT create all the elements of the pane. It creates only the elements of the visible pane and deletes them when the pane is switched away. Therefore, the list may or may not exist.
The UI elements are QWidgets. All QWidgets are QObjects. Any QObject's signals can be connect()ed to any other object's slots. The hierarchy of parent/child relationships is entirely immaterial.
You seem to be confusing signal-slot connections with events, which can be in fact passed up the object hierarchy if they remain ignored by given object.
It's also worth noting that signal-slot connections are safe in spite of QObjects being destroyed. When an object with connected signals or slots gets destroyed, the connections are safely torn down. The only thing you can't do is deleting the sender nor receiver object within a slot - use object->deleteLater() instead.