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?


  • Qt Champions 2016

    @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).


  • Qt Champions 2016

    @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=0

    update:
    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?


  • Qt Champions 2016

    @ModelTech

    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...


  • Qt Champions 2016

    @ModelTech
    No, there are QWidgets stacked in a QStackWidget (the createPage method) but each "page" uses a QGridLayout 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 a QAction instance added, a new button is appended to the corresponding page's layout and when a QAction 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.