0
votes

I searched everywhere and found nothing that solved this. I make a QVBoxLayout and then make a web call for data. When the data comes back I add 4 custom widgets to this QVBoxLayout

verticalLayout->addWidget(nsd);

For the first four this works great. Everything appears as needed. However, I want to delete any one of the four widgets then add a widget at the bottom. Deleting works fine

 verticalLayout->removeWidget(nsd);
delete nsd;

I know it works fine because then that widget not longer draws to my screen. The problem is that adding the widget is not working entirely. I call the same code

verticalLayout->addWidget(nsd);

and checking verticalLayout->count() tells me there are 4 items. The widget is created with the same parent widget as the ones added before. The paint event of the new widget never gets called. Furthermore the 3 that show on the screen show spaced for 3 items. It's not like there's a hole anywhere. I also tried adding then deleting but it's the same problem. The new item never gets drawn and its size never factored in.

1
Are you adding a deleted widget?Edwin Rodríguez

1 Answers

2
votes

If you want to get rid of a widget completely, you only need to destruct it. You don't have to worry if it was in a layout. If the widget is dynamically allocated, then delete nsd is all you need, the layout->removeWidget call is not needed. You also don't have to give widgets any explicit parents - insertion into the layout will set proper parent.

The following works and is safe no matter what is the type of the widget being added/removed. If the deletion had target widget on the call stack, you should use deleteLater instead of plain delete. But this can never be the case when you delete it in response to a signal from an unrelated widget, unless the target widget re-enters the event loop (aargh! it shouldn't).

// https://github.com/KubaO/stackoverflown/tree/master/questions/layout-addremove-37814292
#include <QtWidgets>

int main(int argc, char ** argv) {
   QApplication app(argc, argv);
   QWidget widget;
   QVBoxLayout layout(&widget);
   QPushButton button;
   QLabel label("Hello");
   layout.addWidget(&button);
   layout.addWidget(&label);

   auto onClick = [&]{
      if (layout.count() == 3) {
         delete layout.itemAt(2)->widget();
         button.setText("Add");
      } else {
         layout.addWidget(new QLabel("Hello too!"));
         button.setText("Remove");
      }
   };
   QObject::connect(&button, &QPushButton::clicked, onClick);
   onClick();

   widget.show();
   return app.exec();
}