PDA

View Full Version : Remove a QLayout from QGridLayout



grosem
1st January 2007, 10:00
Happy new Year :D

I have a QGridLayout and added some QLayouts, which I want to remove now:



leftBox->addLayout(itemList[itemID]);
leftBox->removeItem(itemList[itemID]);
itemList[itemID]->setParent(0);


leftBox is my QGridLayout
itemList is a QList which contains Points of QHBoxLayout. The adding of the layouts is no problem.
In this example I want to remove them immediatly. removeItems() puts the removed layouts to the same place (left top corner of the leftBox). I actually thought this is as the added Layouts have still leftBox as parent. So I set another parent, which was useless.

So how can I remove this layouts without deleting the removed layout as I want to add it later again?

jpn
1st January 2007, 11:21
You would have to hide the removed widgets. Removing a widget from a layout only means that the widget is no more managed by the layout and so it will stay in the upper left corner unless it is re-parented. I do personally find it a good idea to avoid dynamically changing layouts as much as possible and use for example a stacked widget or layout instead. Of course they don't fit to all situations. In this case you would most likely have to disable the layout during the changes to avoid the flicker, at least if there are several changes in a row.

grosem
1st January 2007, 12:13
Stacked Layout is no alternative for me, but thanks for your advise, it worked. :)

EDIT: But I got this problem:


QLayout::addChildLayout: layout "" already has a parent

I did


topBox->removeItem(itemList[itemID]);
itemList[itemID]->hide();

After this I tried to add it at another Layout.

I thought by removing the item (which is a layout) I can add it somewhere else. But it seems it still keeps its parent!?

grosem
1st January 2007, 14:02
The only possibility I found is to make a new Item with the same value and delete the old one. But this can't be the right solution, can it?

jpn
1st January 2007, 14:11
QLayout::addChildLayout: layout "" already has a parent
Sounds like you are missing the

itemList[itemID]->setParent(0);
which you had earlier..?

Could you describe the GUI you are building? Maybe there's another way for constructing something similar?

grosem
1st January 2007, 14:28
Sounds like you are missing the

itemList[itemID]->setParent(0);
which you had earlier..?

Could you describe the GUI you are building? Maybe there's another way for constructing something similar?


I tried this too. But got a


X Error: BadWindow (invalid Window parameter) 3
Major opcode: 25 (X_SendEvent)
Resource id: 0x20000ad

Well, I have three frames, which have Items. These items are a QHBoxLayout which has 2 QLabels and a QSpinBox. The user should be able to drag these items between the three frames.

At first I tried the QItemView approach, but I wasn't able to do it the way I wanted.

I know my new approach using Layouts isn't the right one, but it is much simplier for me. Just the thing of removing does not work yet. :(

Thanks for your help :)

jpn
1st January 2007, 15:05
Yeah, the suggestion would have been using item views.. ;)

grosem
1st January 2007, 16:08
I never thought this reuse of Layouts would be a problem :(

grosem
1st January 2007, 18:50
I don't get it:



leftBox->addLayout(protoItem2);
leftBox->removeItem(protoItem2);
protoItem2=0;
delete protoItem2;

Why is there still the layout in the leftBox??? Even more weird is that the added layout had two QLabels, but only one is still visible (the one with a QPixmap). leftBox->update() changes nothing.

jpn
1st January 2007, 18:56
leftBox->addLayout(protoItem2);
leftBox->removeItem(protoItem2);
protoItem2=0;
delete protoItem2; // <--- same as "delete 0;"




leftBox->addLayout(protoItem2);
leftBox->removeItem(protoItem2);
delete protoItem2; // delete first
protoItem2=0; // then set the pointer to 0

grosem
1st January 2007, 19:55
ok, that's of course true, but unfortunatly that does not change something.

I did following: The Items I add to the QGridLayout are from a class derived from QHBoxLayout. I added two QLabels to this class and added them in the Constructor to the QHBoxLayout. I actually though by deleting the object of the class the two QLabels would be deleted too. But apparently that's not the case. Having added this in the destructor


~Item(){delete myName; delete myIcon;}

it works.

Seems very dirty for me :(

jpn
1st January 2007, 20:25
Those widgets are not children of the layout. Widgets added to a layout become children of the widget where the layout is installed on. This is why the widgets didn't get deleted still if the layout was deleted.

grosem
1st January 2007, 20:34
Those widgets are not children of the layout. Widgets added to a layout become children of the widget where the layout is installed on. This is why the widgets didn't get deleted still if the layout was deleted.

Aaah... I was not aware of this. Thank you :)

grosem
2nd January 2007, 09:10
Ok, now the removing of QLayouts works. Unfortunatly I can't add new QLayouts to the QGridLayout at runtime. If I want to add them in the constructor of my QMainWindow it's no problem. But adding them later does not work properly. So the QGridLayout receives the new Layout but does not display it.
I read the Qt-list archive, where someone suggested to call activate on the QGridLayout, but this does not work - not a surprise as this suggestion is from 1998...

Any ideas?

EDIT: update() does not change anything

jpn
2nd January 2007, 09:12
It should work. Did you, by any chance, forget to show() the widgets added at runtime?

grosem
2nd January 2007, 09:21
It should work. Did you, by any chance, forget to show() the widgets added at runtime?

I do the same as I did in the constructor of QMainWindow (where the Items are shown). If I did not have to call show() there explicitly I don't have to do it somewhere else, have I?

The Items I add are looking like that


QHBoxLayout->QFrame->QLabel and QLabel;

If I call show on QFrame it opens seperatly new windows. show() at the QLabels has no effect.

jpn
2nd January 2007, 09:39
I do the same as I did in the constructor of QMainWindow (where the Items are shown). If I did not have to call show() there explicitly I don't have to do it somewhere else, have I?

Child widgets (which are not explicitly hidden) become visible too when their ancestor is shown. So you don't have to explicitly call show() for child widgets created in window constructor or so, as you will call show() for the window later anyway. But later at runtime when the window is already visible, adding more child widgets requires also an explicit show() to be called on the children.



If I call show on QFrame it opens seperatly new windows. show() at the QLabels has no effect.
Sounds like a parenting issue. A widget with no parent is same as a top level window. So the QFrame has no parent. And the QLabel won't be visible if it's parent (QFrame) is hidden.

Double check the code where you do the reparenting/layout switching. There must be a quirk somewhere.

grosem
2nd January 2007, 09:57
EDIT: Maybe I found the problem
EDIT2: Indeed I did. Ok, I did not, but it works now :D . As you said I had to call show() to the single widgets.









Sounds like a parenting issue. A widget with no parent is same as a top level window. So the QFrame has no parent. And the QLabel won't be visible if it's parent (QFrame) is hidden.

Double check the code where you do the reparenting/layout switching. There must be a quirk somewhere.

There was a small mistake: I did it this way

QHBoxLayout->QFrame->QHBoxLayout->QLabel and QLabel;

The additional QFrame is for easy layouting and dragndrop.

So I add the QFrame to the QHBoxLayout. Is not the QHBoxLayout now automatically the new parent? Because of your suggestion I tried



addWidget(itemframe) //it's in the constructor of the derived QHBoxLayout class
itemframe->setParent(this) //this is the QHBoxLayout

but the compiler says that only a QWidget can be the parent of itemframe :-/

btw.: jpn, you're my personal hero for this month :D

jpn
2nd January 2007, 11:19
Glad to hear it finally works. :)

By the way, the usual approach to manage child widgets is to subclass some widget and do the handling there. It is quite unusual to subclass a layout for handling children, at least if no changes to the actual layout handling is made.