QT 5.6 QVBoxLayout removeWidget然后addWidget未按预期工作

QT 5.6 QVBoxLayout removeWidget然后addWidget未按预期工作,qt,qvboxlayout,Qt,Qvboxlayout,我到处都找遍了,没有找到解决这个问题的办法。我制作了一个QVBoxLayout,然后在web上调用数据。当数据返回时,我向这个QVBoxLayout添加了4个自定义小部件 verticalLayout->addWidget(nsd); 对于前四个,这非常有效。一切都按需要出现。但是,我想删除四个小部件中的任何一个,然后在底部添加一个小部件。删除可被罚款 verticalLayout->removeWidget(nsd); delete nsd; 我知道它工作得很好,因为这样小部

我到处都找遍了,没有找到解决这个问题的办法。我制作了一个QVBoxLayout,然后在web上调用数据。当数据返回时,我向这个QVBoxLayout添加了4个自定义小部件

verticalLayout->addWidget(nsd);
对于前四个,这非常有效。一切都按需要出现。但是,我想删除四个小部件中的任何一个,然后在底部添加一个小部件。删除可被罚款

 verticalLayout->removeWidget(nsd);
delete nsd;
我知道它工作得很好,因为这样小部件就不会再出现在我的屏幕上了。问题是添加小部件并不完全有效。我调用相同的代码

verticalLayout->addWidget(nsd);

检查verticalLayout->count()告诉我有4个项目。小部件是使用与之前添加的小部件相同的父小部件创建的。从未调用新小部件的绘制事件。此外,屏幕上显示的3个显示间隔为3个项目。又不是到处都有洞。我也尝试过添加然后删除,但这是相同的问题。新项目从未绘制,其大小从未考虑在内

如果你想完全摆脱一个小部件,你只需要销毁它。你不必担心它是否在布局中。如果小部件是动态分配的,那么您只需要
delete nsd
,就不需要调用
layout->removeWidget
。您也不必给小部件任何显式的父级-插入布局将设置正确的父级

无论要添加/删除的小部件的类型是什么,以下操作都是安全的。如果删除在调用堆栈上有目标小部件,则应使用
deleteLater
而不是普通的
delete
。但是,当您响应来自无关小部件的信号而删除它时,永远不会出现这种情况,除非目标小部件重新进入事件循环(啊!不应该)

//https://github.com/KubaO/stackoverflown/tree/master/questions/layout-addremove-37814292
#包括
int main(int argc,字符**argv){
QApplication应用程序(argc、argv);
QWidget小部件;
QVBoxLayout布局(和小部件);
QPushButton按钮;
QLabel标签(“你好”);
layout.addWidget(&按钮);
layout.addWidget(&label);
自动点击=[&]{
if(layout.count()==3){
删除layout.itemAt(2)->widget();
按钮。设置文本(“添加”);
}否则{
layout.addWidget(新的QLabel(“Hello too!”);
按钮.setText(“删除”);
}
};
QObject::connect(&button,&QPushButton::clicked,onClick);
onClick();
widget.show();
返回app.exec();
}

如果你想完全摆脱一个小部件,你只需要销毁它。你不必担心它是否在布局中。如果小部件是动态分配的,那么您只需要
delete nsd
,就不需要调用
layout->removeWidget
。您也不必给小部件任何显式的父级-插入布局将设置正确的父级

无论要添加/删除的小部件的类型是什么,以下操作都是安全的。如果删除在调用堆栈上有目标小部件,则应使用
deleteLater
而不是普通的
delete
。但是,当您响应来自无关小部件的信号而删除它时,永远不会出现这种情况,除非目标小部件重新进入事件循环(啊!不应该)

//https://github.com/KubaO/stackoverflown/tree/master/questions/layout-addremove-37814292
#包括
int main(int argc,字符**argv){
QApplication应用程序(argc、argv);
QWidget小部件;
QVBoxLayout布局(和小部件);
QPushButton按钮;
QLabel标签(“你好”);
layout.addWidget(&按钮);
layout.addWidget(&label);
自动点击=[&]{
if(layout.count()==3){
删除layout.itemAt(2)->widget();
按钮。设置文本(“添加”);
}否则{
layout.addWidget(新的QLabel(“Hello too!”);
按钮.setText(“删除”);
}
};
QObject::connect(&button,&QPushButton::clicked,onClick);
onClick();
widget.show();
返回app.exec();
}

是否添加已删除的小部件?是否添加已删除的小部件?是否
deleteLater()
会更安全(不知道自定义小部件在做什么)。@OnWhenReady本例中的删除不是从源于目标小部件的事件中执行的,因此可以并且应该立即删除目标小部件。自定义小部件正在做什么并不重要,只要它不重新进入事件循环(执行该操作的小部件在IMHO中被破坏)。这是一个很好的答案。我的问题是我没有在代码里写上什么。我将小部件存储在一个向量中,并调用vec.erase(std::remove(vec.begin(),vec.end(),nsd),vec.end());是哪个从该列表中删除了新项目,但同时也在内存中销毁了它?@ReadyCent您没有将小部件存储在向量中-小部件不是值类,不可移动,并且不能与向量容器一起使用。您正在向量中存储指向小部件的指针。指针类型的值没有什么特别之处。容器将其视为
intptr\t
。它不会触及指向的数据(如果有的话)-这不是它的工作。在不知道自定义小部件正在做什么的情况下,
deleteLater()
不是更安全吗?@OnWhenReady本例中的删除不是从源于目标小部件的事件中执行的,因此可以而且应该立即删除目标。自定义小部件正在做什么并不重要,只要它不重新进入事件循环(执行该操作的小部件在IMHO中被破坏)。这是一个很好的答案。我的问题是我没有在代码里写上什么。我将小部件存储在一个向量中,并调用vec.erase(std::remove(vec.begin(),vec.end(),nsd),vec.end());是哪个从该列表中删除了新项目,但同时也在内存中销毁了它?@ReadyCent您没有将小部件存储在向量中-小部件不是值类,不可移动,并且不能与向量容器一起使用。你是史托尔
// 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();
}