Search code examples
c++qtqwidgetqlayout

can't remove custom QWidget from QVBoxLayout


This is a reasonably well documented issue but after some reading and trying, I am still struggling to remove a custom widget from a QVBoxLayout.

in the MyClass.h file, I am declaring a vector to hold QPointer objects:

vector< QPointer<MyWidget> > myWidgets;

In the MyClass.cpp file, I am creating the widget and adding it to the layout with:

// create object
void MyClass::createMyWidget() {
    QPointer<MyWidget> myWidget(new MyWidget());
    myWidgets.push_back(myWidget);
}

//display in layout
void MyClass::displayWidgets() {
    for(int i = 0; i < myWidgets.size(); i++) {
        myWidgets[i]->setId(i);
        ui->myVBoxLayout->addWidget(myWidgets[i].data());
    }
}

I have tried the following to remove the widgets from the layout:

void MyClass::removeMyWidget(int id) {    // id of the custom widget. id is also position in the layout
    for(int i = 0; i < myWidgets.size(); i++) {
        if(items[i]->getId() == id) {  //correctly targets the widget
            // method 1
            ui->myVBoxLayout->removeItem(ui->myVBoxLayout->takeAt(i));

            //method 2
            //ui->myVBoxLayout->removeWidget(items[i]);
        }
    }
}

Neither of the above works and I have not been able to work out why.


Solution

  • In Qt, a layout is just a manager for sizing and positioning widgets (and other items, like nested layouts or spacers).

    When you remove an item from a layout, it is still a child-widget of the parent widget that is layed out by the layout, only that its geometry is no longer managed. Still, the widget is present and displayed, and the user can interact with it.

    You also have to remove it or hide it. Try

    void MyClass::removeMyWidget(int id){    // id of the custom widget. id is also position in the layout
        for(int i=0;i<myWidgets.size();i++){
            if(items[i]->getId() == id){  //correctly targets the widget
                ui->myVBoxLayout->removeWidget(myWidgets[i]);
                delete myWidgets[i]; // <= Delete widget
            }
        }
    }