Unsolved Adding & Deleting Rows to/from QGridLayout
-
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?
-
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?
-
@ModelTech said:
How to enforce QGridLayout to delete rows that do not contain any Widgets anymore?
You can't, you have to manually shift up (left) all cells below (right).
-
@ModelTech said:
delete Object;
does this delete the widgets also?
Object will delete its widgets. ?removeWidget only removes from grid management.
They are still drawing.works for me in this mini sample based on ur code
https://www.dropbox.com/s/1y693yg1w409vr1/mygridlayout.zip?dl=0update:
Oh, you want to remove random rows ?
I assumed u removed last.well then @kshegunov beat me to it :)
-
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).
And yes, I want to delete random rows, not necessarily the last one.
-
@mrjj said:
does this delete the widgets also?
Yes, it does...
@kshegunov said:
@ModelTech said:
How to enforce QGridLayout to delete rows that do not contain any Widgets anymore?
You can't, you have to manually shift up (left) all cells below (right).
How can I implement a shift up / down?
-
You can use QLayout::takeAt() and QLayout::count() to get the layout items back from the layout. Some time ago I needed a dial widget that managed tool buttons from
QAction
instances, here's the code if you'd want to take a look. There's item removal when actions are added/removed, so you can draw some inspiration from it.Edit: Specifically, look here and here.
Kind regards.
-
Thanks for that @kshegunov. If I understand your code correctly, then you seem to rely on count() for QStackLayout. As it turns out rowCount() for QGridLayout does not reduce when deleting all widgets of some row...
-
@ModelTech
No, there areQWidgets
stacked in aQStackWidget
(thecreatePage
method) but each "page" uses aQGridLayout
in which it puts buttons. The pages are organized in a tree, where each page gets a return button in the beginning. When there's aQAction
instance added, a new button is appended to the corresponding page's layout and when aQAction
is removed the button is removed. The interesting part, at least for you, is how the layout is "recreated" in AgDialPrivate::invalidateLayout when a button is added or removed.
Basically the idea is this:- everything after button index
from
have to be moved to its proper position, because after removing a button (layout item) there's a hole left in the layout. - every layout item that's after index
from
is taken out of the layout (line 58) and put into a stack for reinsertion. - for each of the extracted items a new position is calculated based on the total number of items in the grid (line 62)
- the item is reinserted in the layout at its new and correct position (line 63)
The function uses the internal index of the items which is independent of their position (row, column) in the layout for extraction, and then based on the number of items the row and column is calculated, and finally the item is reinserted in the correct cell.
- everything after button index