PDA

View Full Version : Remove column from QGridLayout



enricong
27th June 2012, 16:10
I have a qgridlayout which consists of a grid 3 rows and X columns. It starts as one column. I then programatically add columns using "addWidget" adding to rows 0 and 1 in a new column. This works fine. I would like to then delete all the columns (except the first) then start over adding new columns the same way. I tried using "removeItem" but this does not seem to work.



//Add columns
QGridLayout *layout = ui->gridlayout;
Qlabel label, label2;
QGraphicsView gv, gv2;

layout->addWidget(label1,0,1)
layout->addWidget(gv1,1,1)
layout->addWidget(label2,0,2)
layout->addWidget(gv2,1,2)




//Remove columns
QGridLayout *layout = ui->gridlayout;

layout->columnCount() // 3 as expected

layout->removeItem(layout->itemAtPosition(0,1)
layout->removeItem(layout->itemAtPosition(1,1)

layout->columnCount() // Still 3, expecting 2

layout->removeItem(layout->itemAtPosition(0,2)
layout->removeItem(layout->itemAtPosition(1,2)

layout->columnCount() // Still 3, expecting 1

high_flyer
27th June 2012, 17:30
Why is it important for you to have the layout with specific amount of column/rows?
Layouts are not made for you to manage - but to take the layout management from you!
Since you don't have to add N columns when you want the first item to be at N+1, similarly you don't have to do anything when you remove an item from the layout.
Maybe if you explain why this is important for you, a better way of solving it can be suggested.

enricong
27th June 2012, 18:05
I dont specifically want to change the layout directly. I am just removing items from the layout. I expect the layout to automatically remove the columns but it does not seem to be doing that.

perhaps I implemented this in the wrong way.

I would like to display the following in a box:

first line: QLabel
second line: QGraphicsView
Third line: QSlider

My program uses a set of images of the same thing taken over time. When the users clicks on a specific part of the image, I would like the bottom to fill with image tiles of the corresponding zoomed in section on all the other images.

So when a user double clicks, I open each image and pull the tile out. I would like to display all the tiles in one row. I would like the date and time of the image to show on top. The first image has a QSlider below it to give the option for the user can move the slider and see the image difference on top of each other. To keep things aligned and to help with resizing, I put it all in a gridlayout and programatically add columns for each tile.

Since the number of tiles may change, each time the user double clicks on a part of the image, I would like each tile to be removed to make room for the new tiles to be added.

So far it is working, except if I double click on a different part of the image, I have no way to remove the tiles that I just added.

high_flyer
28th June 2012, 09:55
So far it is working, except if I double click on a different part of the image, I have no way to remove the tiles that I just added.
Why not?
QLayout::removeItem() (http://qt-project.org/doc/qt-4.8/qlayout.html#removeItem)
QLayout::removeWidget() (http://qt-project.org/doc/qt-4.8/qlayout.html#removeWidget)

That is the point I was making.
You are trying to manage the layout - but you don't have to, this is what QLayout is for.
Manage your widgets instead!

enricong
28th June 2012, 14:22
That is what my first message said and my original question.
I use QLayout::removeItem() but it doesn't get removed.

high_flyer
28th June 2012, 14:28
i use qlayout::removeitem() but it doesn't get removed.
Oh, I see now.
But you "are doing it without doing it".
What I mean is, you ask the layout for the items.
Instead, you must have the pointers to the objects somewhere right, so use these pointers in remoevItem() - don't ask the layout for them.

To do it the way you are doing it, you need to keep track of everything you add and remove to the layout, but why would you want to do that - that is what the layout it for!
Asking the layout for the viewer in a given cell only guarantees you that you get a pointer to a viewer (if any) which is in that cell - but if your bookkeeping is wrong, you are not getting the viewer you expect, or, not any viewer at all.

enricong
28th June 2012, 17:43
Oh, I see now.
To do it the way you are doing it, you need to keep track of everything you add and remove to the layout, but why would you want to do that - that is what the layout it for!


I think I see what you mean.
I was was not tracking the pointers after they are added to the layout.
I was depending on the ability to find the pointer by asking the layout.

Therefore, what would you propose is the best way I can accomplish this.

I can try tracking all my pointers and deleting directly but as you say "thats what a layout is for"
I can also ask the layout for the items, but that doesnt seem to be working right for me.

high_flyer
29th June 2012, 11:07
Hmm... after thinking about it a bit more:

I am not sure what's QLayout policy in a case when you add a viewer to an already occupied cell.
Does it put the widgets on top of each other or creates a new row/column (cell).
I'd expect the later which is the reason I thought working with the layout position is not reliable.
However if the layout stacks the widgets, then your approach should work, but the question then is, which of the stacked widgets (in a cell) do you get?

Test it.


At any rate, you don't really need to track or manage anything, you just need to store the pointers of your widgets.
A QVector, or a QList is ok.
You don't need the layout position if you have the pointer.
Unless you allocate your items as children, you need these pointers to delete them, otherwise you get a memory leak.

Mini4Ever
20th August 2016, 10:18
Reviving this very old thread as I have a similar problem...

I have a QWidget that includes a QGridLayout Layout. This QGridLayout has on each row two QLineEdit's and one QPushButton, which are part of an Object of MyClass. The Layout has one header row at the top (row 0) and all Objects are stored in the ObjectList (a QList).

I have written the following code to remove a row regarding a specific Object.


// Deleting an Object
Layout->removeWidget(Object->LineEdit1());
Layout->removeWidget(Object->LineEdit2());
Layout->removeWidget(Object->PushButton());
ObjectList.removeOne(Object);
delete Object; // Deletes its LineEdit1, LineEdit2 and PushButton

To add a row for a new Object, I have the following code.


// Adding a new Object
MyClass *Object = new MyClass; // Creates its LineEdit1, LineEdit2 and PushButton
ObjectList.append(Object);
Layout->addWidget(Object->LineEdit1(), ObjectList.size() + 1, 0);
Layout->addWidget(Object->LineEdit2(), ObjectList.size() + 1, 1);
Layout->addWidget(Object->PushButton(), ObjectList.size() + 1, 2);

For some reason this code does not always work according to my expectation. In some situations the new Object does become visible and in other situations not, or at least no new row becomes visible (while the new Object is actually created). It seems that an existing row is basically overwritten with a row for the new Object.

Anyone a clue of what I am doing wrongly?

Edit: I may have clarified the symptom a bit: It seems that if not the last row in the QGridLayout deleted but any other row, a subsequent addition of a new row overwrites a row that remained to exist. How to enforce QGridLayout to delete rows that do not contain any Widgets anymore?

Reviving this very old thread as I have a similar problem...

I have a QWidget that includes a QGridLayout Layout. This QGridLayout has on each row two QLineEdit's and one QPushButton, which are part of an Object of MyClass. The Layout has one header row at the top (row 0) and all Objects are stored in the ObjectList (a QList).

I have written the following code to remove a row regarding a specific Object.


// Deleting an Object
Layout->removeWidget(Object->LineEdit1());
Layout->removeWidget(Object->LineEdit2());
Layout->removeWidget(Object->PushButton());
ObjectList.removeOne(Object);
delete Object; // Deletes its LineEdit1, LineEdit2 and PushButton

To add a row for a new Object, I have the following code.


// Adding a new Object
MyClass *Object = new MyClass; // Creates its LineEdit1, LineEdit2 and PushButton
ObjectList.append(Object);
Layout->addWidget(Object->LineEdit1(), ObjectList.size() + 1, 0);
Layout->addWidget(Object->LineEdit2(), ObjectList.size() + 1, 1);
Layout->addWidget(Object->PushButton(), ObjectList.size() + 1, 2);

For some reason this code does not always work according to my expectation. In some situations the new Object does become visible and in other situations not, or at least no new row becomes visible (while the new Object is actually created). It seems that an existing row is basically overwritten with a row for the new Object.

Anyone a clue of what I am doing wrongly?

Edit: I may have clarified the symptom a bit: It seems that if not the last row in the QGridLayout deleted but any other row, a subsequent addition of a new row overwrites a row that remained to exist. How to enforce QGridLayout to delete rows that do not contain any Widgets anymore?

Added after 1 45 minutes:

Ok, I found a solution, but I am not sure whether I like it... I changed the code to add an Object to:


// Adding a new Object
MyClass *Object = new MyClass; // Creates its LineEdit1, LineEdit2 and PushButton
ObjectList.append(Object);
int Count = Layout->rowCount();
Layout->addWidget(Object->LineEdit1(), Count, 0);
Layout->addWidget(Object->LineEdit2(), Count, 1);
Layout->addWidget(Object->PushButton(), Count, 2);


Is this really the way it should be done? I would expect that this creates a lot of empty rows / cells in the QGridLayout that only consume memory (although probably not much).

anda_skoa
20th August 2016, 11:37
The grid layout doesn't have any methods to remove cells, so if you need them removed you need to recreate the layout,

Alternatively you can move all content below the cleared row upwards so that empty rows are at the end and then reuse those when adding new items.

Cheers,
_