PDA

View Full Version : Parent child relationship in Qt



TheIndependentAquarius
10th May 2011, 11:51
Every widget has a parent which helps in cases of deletion, i.e. when the parent gets deleted, the child gets automatically thrown out to /dev/null.

Now I see QWidget *parent being passed to the user defined class's constructor here, in this link: http://doc.qt.nokia.com/4.7/tutorials-addressbook-part1.html

class AddressBook : public QWidget
{
Q_OBJECT

public:
AddressBook(QWidget *parent = 0);

private:
QLineEdit *nameLine;
QTextEdit *addressText;
}; What does this indicate? In what way is this useful?

Zlatomir
10th May 2011, 12:37
When you create the object (instance of your class) you can pass a QWidget pointer (the address of the parent).
Example


AddressBook *myAddressBook = new AddressBook (pointerToTheParent);

Or if you don't pass a pointer to parent the object will have no parent (that is what the = 0 means: the parent pointer is NULL) and if the object doesn't get a parent (like when you add it to a layout it gets parented automatically) you will need to delete it (only if allocated on the heap).

Hope i managed to clear things a little bit ;)

TheIndependentAquarius
10th May 2011, 12:50
Thanks for responding, but situation is still not crystal clear. Now since I have mentioned the parent's pointer in the 'AddressBook''s constructor, won't I have to manually delete it, if I allocate it with new?

What are the other uses of mentioning the parent pointer?

Archa4
10th May 2011, 12:55
If you mentioned the parent, then when you delete your parent the child will be deleted with it...

TheIndependentAquarius
10th May 2011, 12:57
I know that, my in the OP the parent is QWidget itself. How should I delete it?

Zlatomir
10th May 2011, 13:03
Thanks for responding, but situation is still not crystal clear. Now since I have mentioned the parent's pointer in the 'AddressBook''s constructor, won't I have to manually delete it, if I allocate it with new?

If it doesn't have a parent you need to delete it.
If it has a parent - the parent will delete it, you need to make sure that in parent-child "chain" the "parent of everything" gets deleted (either manually <delete call> or by creating it on stack)


What are the other uses of mentioning the parent pointer?

Memory management, the parent show/hide it's children widgets (if they are not a new window - or explicitly hidden by programmer), the layout system uses the parent-child relationship, i'm sure that there are many other things that i might forgot - you need to practice with C++ and Qt and you will discover and learn them.

This (http://doc.qt.nokia.com/4.7/qt-basic-concepts.html) documentation page has links to basic "patterns" used with Qt - as i said i'm sure there are other places where parent-child relationship is useful.

Archa4
10th May 2011, 13:05
If u have AddressBook(QWidget *parent = 0),
then by default the parent is the one in which u have created the addressbook

TheIndependentAquarius
10th May 2011, 13:12
If it has a parent - the parent will delete it, you need to make sure that in parent-child "chain" the "parent of everything" gets deleted (either manually <delete call> or by creating it on stack)
Yeah, and in this case, "QWidget" class is itself the parent, so you mean to say that I need to delete the QWidget pointer, to get the addressbook object deleted?

If yes, then what's the way to delete the QWidget pointer which I haven't initialized even?


the parent show/hide it's children widgets (if they are not a new window - or explicitly hidden by programmer), the layout system uses the parent-child relationship,
Thanks, I'll read about "show/hide" thing, this link is what you were referring to: http://doc.qt.nokia.com/4.7/objecttrees.html ? That seems to be helpful, I'll go through it.

Zlatomir
10th May 2011, 13:23
Yeah, and in this case, "QWidget" class is itself the parent, so you mean to say that I need to delete the QWidget pointer, to get the addressbook object deleted?

You don't delete the QWidget pointer from your class definition.

You just need to make sure the parent, if any, gets deleted (the parent is passed when you construct the object)
Ok, example code:


#include <QtGui>
#include "addressbook.h"
//...every needed header

int main(...) {
//QApplication app ....
QWidget *parent = new QWidget; //a parent for your addressbook
AddressBook *myAddressBook = new AddressBook(parent); //pass a pointer to parent widget when you construct an AddressBook object
//... other code, maybe some layout if necessary...
parent->show(); //will show the chidren widgets too

int returnValue = app.exec();
delete parent; //this will delete the parent children too
return returnValue;
}

or you can create the parent on the stack and you don't have to call delete:

int main(...) {
//QApplication app ....
QWidget parent; //a parent for your addressbook - parent is created on stack
AddressBook *myAddressBook = new AddressBook(&parent); //pass a pointer to parent widget when you construct an AddressBook object
//... other code, maybe some layout if necessary...
parent.show(); //will show the chidren widgets too

return app.exec();
}

DanH
11th May 2011, 03:26
I think you may be confusing several things here --

First off, in this example AddressBook is a subclass of QWidget. This has nothing to do with parent/child relationships (other than the fact that the implementation of AddressBook's constructor needs to be sure to cascade the "parent" pointer to QWidget's constructor). The parent/child relationship and the subclass/superclass relationship are entirely separate and distinct things.

Second, the idiom "(SomeClass* someParameter = 0)" defines an "optional" parameter. That is, the "= 0" means that if you don't code the parameter (ie, in this case just code "AddressBook()" for the constructor) then it's as if you had coded "AddressBook(NULL)", passing a null value for the parent.

Third, the parent-child relationship is used for several things. For all QObjects (not just QWidgets) there's the automatic destruction function. For all QWidgets there's a relationship in terms of how graphics are built and displayed -- children paint on their parents, hiding a parent hides the children, etc. For many parent-child relationsips (mostly between QWidgets) events of certain types (particularly key and touch events) are propagate to the parent if the child doesn't handle them.

Lykurg
11th May 2011, 07:11
If u have AddressBook(QWidget *parent = 0),
then by default the parent is the one in which u have created the addressbook

No thats wrong. If you don't pass a parameter then the widget has no parent and you need to delete it yourself.

kosasker
12th July 2011, 09:04
Hi. I have same question with a little difference. I build a form with tab widget. After running, i make it unvisible, and call with another button click. On close the child form is deleting with own objects. My problem is, with tab widget. Because i call it with reference, so on child form close its deleting from heap. After that if i click the button second time, its crashing. I cant copy my existed tab widget, or cant create a copy. How can i do it ?

Here is my dirty code



void MainWindow::on_action_Config_triggered()
{
confw = new QDialog(this);
confw->setModal(true);
confw->setSizeGripEnabled(false);

confw->setObjectName("confwid");
confw->setWindowTitle("Configuration");

QWidget *tab = new QWidget;
tab = (QWidget *)ui->tab1; //existing tab widget object, which i created with qt creator for another mainwindow object
tab->setParent(confw); // on confw delete, its deleting too. because i cant make it copy!!! :(

tab->show();
confw->setMaximumSize((tab->width()+10),(tab->height()+10));
confw->setMinimumSize((tab->width()+10),(tab->height()+10));
ui->pushButton->setVisible(false);
confw->resize(tab->size().width()+10,tab->size().height()+10);
confw->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,confw->size(),
qApp->desktop()->availableGeometry()));

QPushButton *pushbutton = new QPushButton(ui->groupBox_6);
pushbutton->setText("Save");
pushbutton->setGeometry(ui->pushButton->geometry());
pushbutton->setIcon(ui->pushButton->icon());
connect(pushbutton,SIGNAL(clicked()),this,SLOT(con figcontrol()));
connect(pushbutton,SIGNAL(clicked()),confw,SLOT(cl ose()));
ui->groupBox_6->setVisible(true);
ui->groupBox_6->setEnabled(true);
pushbutton->setVisible(true);
pushbutton->setEnabled(true);
pushbutton->show();
confw->showNormal();
}


Regards.

kosasker
13th July 2011, 07:09
Any suggestions ?

Santosh Reddy
13th July 2011, 07:40
create confw as class member variable and don't delete it, just close and show it as and when required.

and moreover looks like you are complicating the situation here, I was not able to understand what you are trying to do:confused:, if you could explain how you want things to displayed I can suggest something simple:)

kosasker
13th July 2011, 12:08
My english is really bad. Pardon me.
Thanks Santosh :) There is just tab object i have. i didnt want to make a new one. After my application run, i m controlling the user input datas. if there is no data in registry, user can input the data by using this tab and tab objects(lineedits, etc.). else if they are recorded in the registry, then removing tab1 object from tabwidget, so i hide it. If user wants to change these datas, just need to click "config" action in menubar object. And then my goal is starting :) . As you said, i didnt delete confw object. But its making memory leak! i just want to copy my tab1 object.

confw object is dynamic, but ui->tab1 object is static. tab1 object creating for just one (1) time on application running. But confw object is creating at every "config action" triggered. So, i need to make tab1 object as dynamic.

i can make a new tab object like "tab1" with creating all components again one by one. But i didnt want to do it. I just want to use existing tab.

Wish i can explain myself.

Thanks.

DanH
13th July 2011, 12:55
[Someone turned the posts order upside down on me]

Santosh Reddy
13th July 2011, 13:22
make confw and ui->tab1 static, add confw to tab widget as a page dynamically, and hide / show dynamically in on_action_Config_triggered()

You may need to check you logic again, you wanted to add a page in tab widget, then why do you create QDialog in on_action_Config_triggered()?

1. Do you want to show configuration widget / form in tab widget as a page?
or
2. Do you want to show confguration widget / form as dialog?

this what you code does (as posted above)
1. Creates a configuration QDialog (confw)
2. Adds a new QWidget (tab)
3. assign ui->tab1 to tab, the QWidget created in step 2 is lost, this is memory leak - Why do you do this?

You are mixing tab widget & QDialog, I hope you are getting my point

kosasker
13th July 2011, 15:49
Thanks for answer again. After creation confw, i were closed it, when my job is completed. Not hiding :)

i' m making show & close... Not show&hide.... Difference is that. Thank you. i will hide it... why i never think about it? i always closing or destroy my forms.. :)
Thanks again ;)

kosasker
14th July 2011, 08:43
Hi. Sorry for late. My solution is here.



void MainWindow::on_action_Config_triggered()
{
QDialog *dia = this->findChild<QDialog *>("confwid"); // with this code, i' m finding object from object name
if (dia == 0) // if object confwid is not exist, value is "0" (zero), then i 'm creating object.
{
confw = new QDialog(this);
confw->setModal(true);
confw->setSizeGripEnabled(false);

confw->setObjectName("confwid"); // object name is here :)
confw->setWindowTitle("Configuration");

QWidget *tab = new QWidget;
tab = (QWidget *)ui->tab1; //existing tab widget object, which i created with qt creator for another mainwindow object
tab->setParent(confw);

tab->show();
confw->setMaximumSize((tab->width()+10),(tab->height()+10));
confw->setMinimumSize((tab->width()+10),(tab->height()+10));
ui->pushButton->setVisible(false);
confw->resize(tab->size().width()+10,tab->size().height()+10);
confw->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,confw->size(),
qApp->desktop()->availableGeometry()));

QPushButton *pushbutton = new QPushButton(ui->groupBox_6);
pushbutton->setText("Save");
pushbutton->setGeometry(ui->pushButton->geometry());
pushbutton->setIcon(ui->pushButton->icon());
connect(pushbutton,SIGNAL(clicked()),this,SLOT(con figcontrol()));
connect(pushbutton,SIGNAL(clicked()),confw,SLOT(hi de())); // with pushbutton clicked, i' m hiding QDialog. Not close!
ui->groupBox_6->setVisible(true);
ui->groupBox_6->setEnabled(true);
pushbutton->setVisible(true);
pushbutton->setEnabled(true);
pushbutton->show();
confw->showNormal();
}

else // if confwid named object is avaible, i just setting geometry and setting visibilty true for showing.
{
this->confw->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,confw->size(),
qApp->desktop()->availableGeometry()));
this->confw->setVisible(true);
}
}


QObject::findChild (http://doc.qt.nokia.com/latest/qobject.html#findChild)

Its working clearly. That' s it. Thanks. :)