【问题标题】:QT 5.6 QVBoxLayout removeWidget then addWidget not working as expectedQT 5.6 QVBoxLayout removeWidget 然后 addWidget 没有按预期工作
【发布时间】:2016-06-14 23:51:06
【问题描述】:

我到处搜索,没有找到解决这个问题的方法。我制作了一个 QVBoxLayout,然后对数据进行了网络调用。当数据返回时,我将 4 个自定义小部件添加到此 QVBoxLayout

verticalLayout->addWidget(nsd);

对于前四个,这很有效。一切都按需要出现。但是,我想删除四个小部件中的任何一个,然后在底部添加一个小部件。删除工作正常

 verticalLayout->removeWidget(nsd);
delete nsd;

我知道它工作正常,因为那个小部件不再绘制到我的屏幕上。问题是添加小部件不能完全正常工作。我调用相同的代码

verticalLayout->addWidget(nsd);

检查verticalLayout->count() 告诉我有4 个项目。小部件是使用与之前添加的相同的父小部件创建的。新小部件的绘制事件永远不会被调用。此外,屏幕上显示的 3 显示间隔为 3 个项目。这不像是任何地方都有一个洞。我也尝试添加然后删除,但这是同样的问题。新项目永远不会被绘制,它的大小也永远不会被考虑在内。

【问题讨论】:

  • 您要添加已删除的小部件吗?

标签: qt qvboxlayout


【解决方案1】:

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

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

// 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();
}

【讨论】:

  • deleteLater() 不会更安全(不知道自定义小部件在做什么)。
  • @OnWhenReady 此示例中的删除不是从源自目标小部件的事件完成的,因此可以并且应该立即删除目标。自定义小部件在做什么并不重要,只要它不重新进入事件循环(这样做的小部件已损坏恕我直言)。
  • 这是一个很好的答案。我的问题是我没有放入代码中。我将小部件存储在向量中并调用 vec.erase(std::remove(vec.begin(), vec.end(), nsd), vec.end());哪个从该列表中删除了新项目,但也在内存中销毁了它?
  • @ReadyCent 您没有将小部件存储在矢量中 - 小部件不是值类,不可移动,并且不适用于矢量容器。您正在将指向小部件的指针存储在向量中。指针类型的值没有什么特别之处。容器将其视为intptr_t。它不会触及指向的数据(如果有的话)——这不是它的工作。
猜你喜欢
  • 2018-08-17
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 2019-09-27
  • 2021-10-19
  • 2020-03-18
相关资源
最近更新 更多