PDA

View Full Version : changing layout of a widget



mikro
17th June 2006, 00:11
hi,
i have a widget called gBAttribute on a MainWindow called configWindow and i want to change it's layout to a VBoxLayout which is returned by the function aart::getEigenschaftenEdit(this) First i had not read the f** manual and tried to do that without deleting the current layout:

this->gBAttribute->setLayout(aart.getEigenschaftenEdit(this));
this gave me the following error:

Attempting to add QLayout "" to ConfigWindow "ConfigWindow", which already has a layout.
QWidget::setLayout() : Attempting to add QLayout "" to QGroupBox "gBAttribute", which already has a layout
so i added some code to delete the current layout before:

QLayout * ql = this->gBAttribute->layout();
if (ql) {
delete ql;
}
this->gBAttribute->setLayout(aart.getEigenschaftenEdit(this));
now console only tells me

Attempting to add QLayout "" to ConfigWindow "ConfigWindow", which already has a layout
does deleting the layout of one widget mean i have to redo all layouts of the parents ???

wysota
17th June 2006, 01:06
Maybe instead of trying to replace the default layout, maybe you could add a new one as child of the default one using QLayout::addItem()?

mikro
17th June 2006, 12:30
no, i am afraid i can't. Let me try to explain what i am trying to do, maybe you can give me another idea on how:
this form allows adding and removing of attribute-types to certain object-types. each object can have any number of attributes from 0 (when it has been newly created) to many. Attributes exist in a different table databasewise, they are attributes like length, width, weight, volume... objects might be a pipe or a manhole of a sewage-system, but might as well be a pump. So e.g. while you will want a pipe to have the attributes length and diameter, they make no sense for a pump. Therefore, and as the Objecttypes used are also not known beforehand, but can be configured by the User, in Configuration the User can choose which of the existing attributes are to be filled in for any objecttype.
To allow this i have this area (gBAttribute) where i add the names of all attributes that have allready been given to it as QLabels with a QPushButton on the side to remove it, and below one dropdownbox of all attributes that have not yet been given to it.

-----------------------------
| Length [remove] |
| Width [remove] |
| ChooseMore \/ |
-----------------------------
now when the user changes to the next objecttype this might not have any attributes at all yet, therefore i need to completly remove everything within gBAttribute and fill it anew. I thought the easiest way would be to delete the QVBoxLayout in gBAttribute, expecting Qt to delete any childs of the layout itself.

wysota
19th June 2006, 15:20
Why don't you use QStackedWidget and implement every set of attributes on a separate page?

mikro
19th June 2006, 22:20
well that might have been a provisionary solution just to allow me to keep on working. But in the long run there might be too many different object-types. A stacked widget might be a nice idea for up to 5 or possibly 10 different object types, but beyond it gets crowded.

now i tried to really use addLayout, instead of deleting ql and replacing it i am trying to delete all of its children and add the layout that aart.getEigenschaftenEdit(this) produces.

QLayout* gbl = this->gBAttribute->layout();
if (!gbl) { // this should not happen and so far it didn't
qDebug() << "gbl non-existent";
QVBoxLayout* vb = new QVBoxLayout(this);
this->gBAttribute->setLayout(vb);
QLayout* gbl = this->gBAttribute->layout();
if (gbl) {
qDebug() << "Layout has been created";
} else {
qDebug() << "bullsh..";
}
}
// we will use gbl as a layout, but we remove every widget and layout
// that might still be in there
int ctItems = gbl->count();
if (ctItems > 0) {
for (int i = 0; i < ctItems; ++i) {
QLayoutItem* tdel = gbl->itemAt(i);
gbl->removeItem(tdel);
if (tdel->widget()) {
qDebug() << "removing Widget" << tdel->widget()->objectName();
}
if (tdel->layout()) {
qDebug() << "removing Layout" << tdel->layout()->objectName();
}
delete tdel;
}
} else {
qDebug() << "no Items found in gbl";
}
gbl->addItem(aart.getEigenschaftenEdit(this));
When i debug this, i can go through this function line by line and only afterwards it crashes, while being in some qt-files :(
At first the class of which aart is an instance was inherited from QVBoxLayout and it didn't crash but i didn't get to see anything (even though obviously the layout had been added, as i could see it being deleted when the function was run again). I assum that was because i had not created some necessary functions. so i checked the manual found how to make your own Layout and mostly copied that. So now my class is inheriting from QLayout and doing everything itself. Since then i just get to see crashes without understanding why they happen ;(
I'd love to use QVBoxLayout to inherit from, but for some reason i can't find the Sourcefile, so i don't know how it works ;(

wysota
19th June 2006, 22:55
Ok, another idea... Maybe you could hide() and show() particular widgets instead of modifying the layout?

mikro
19th June 2006, 23:06
yes, that would work. though what i dislike is that i would have to set them all up at the beginning and have them all in memory even if i later only need one or two of them. Thank you for your quick reply though, but right now i found out, why i had not found the sourcefile for QVBoxLayout: it is in the QBoxLayout.cpp and .h ;)
So now i am using the source of QVBoxLayout as the base of my own class, inheriting from QBoxLayout, which is much easier than trying to inherit from QLayout. Therefore i hope i might be able to make this work without crashing. I still think deleting the old layout and using setlayout to create a new would have been the clean way to go, but i wonder if there might be a bug there... i have been searching all forums that i could find listed on trolltech (yes, even the chinese ;) ... i can't read that, but i could read the source of everything that came when i searched for setLayout there and it doesn't look as if anybody had the problem there.)
Still i found someone in the german forum qtforum.de which i am also frequenting who had the problem, and someone else pushed the thread in february also hoping for a solution. So obviously others have encountered this problem ... is there a way to file a bug when you only use the gpl-version?

mikro
19th June 2006, 23:30
right, now i am close to where i was, when i was still inheriting from QVBoxLayout: no crash, but nothing to see as well. these are the messages i get on the console:


settin "02.10" "Bauwerke in der Kanalisation" // see the code posted above
no Items found in gbl // in the Designer i had added an empty layout for gbl
Attempting to add QLayout "" to ConfigWindow "ConfigWindow", which already has a layout. // i don't have any idea where this message comes from.
// please see the code above - i am not yet adding a layout
// and i never add it to ConfigWindow

// the next two messages are from aart.getEigenschaftenEdit(this), this is why i think the error above is coming too early. i get told, that 2 elemens have been successfully added to the layout, so i should be able to see something
es werden bereits 0 Atribute verwendet. Weiter 2 k÷nnen hinzugewõhlt werden
Das Eigenschaftenlayout hat jetzt 2 Elemente

// now a second call to the function
settin "02.10.60" "Verbindungsbauwerk"
removing Layout "" // this means that obviously i have been able to add a layout at the first try. so why can't i see anything??

wysota
20th June 2006, 07:36
You might want to check the tasktracker on Trolltech site to see if this problem has been reported (and maybe also fixed).

mikro
7th July 2006, 13:11
right, after some discussion with Qts excellent support and a lot of trying i figured out what the problem is and how to circumvent it:
QLayouts inherit from QObject so you can assume them to kill all their children if you delete them. Unfortunately everything that inherits from QWidget can only have a QWidget as a parent. QLayouts are not QWidgets so all the QWidgets that are added to the layout have the layouts parentWidget as a parent not the layout. Therefore they are not deleted when the layout is deleted.
The only way to make this work is to add a widget on the layout and then use this as parent for all the other widgets.
i have added a test-project which shows how it works.

windsword
4th August 2009, 21:21
Does this still stand (with Qt v. 4.5) I defined a class similar to Form, and instead of using the ui file and the command setupUI( this ), I implemented my own UI using discrete widgets.

The slot is implemented in similar fashion, but my code hangs with the following error line:

home_window.cpp: In member function ‘void CentralPage::addExperimenterSlot()’:
home_window.cpp:231: error: ‘schPatGB’ was not declared in this scope

Where schPatGB is a similar group box as "gb" in the sample code. Why, am I not able to call it directly from the slot function which it my case, it reads:

void CentralPage::addExperimenterSlot(void)
{
QString round;
round.setNum(iCount);
qDebug() << "------------ new Turn ----------";
const QObjectList &all = schPatGB->children();
....


// Sal Aguinaga