如何从 Qt 中的布局中删除小部件
How to remove widgets from layout in Qt
我有一段代码可以执行此操作:名为 prepareUI
的方法使 UI 准备好加载输入的搜索结果。当需要清除已经显示的结果时调用名为 onClear
的方法。还有一个名为 populateSearchResults
的方法,它获取搜索数据并用它加载 UI。保存数据的容器是一个公开可用的指针,因为它需要清除 onClear
:
的结果
void MyClass::prepareSearchUI() {
//there may be many search results, hence need a scroll view to hold them
fResultsViewBox = new QScrollArea(this);
fResultsViewBox->setGeometry(28,169,224,232);
fSearchResultsLayout = new QGridLayout();
}
void MyClass::onClear() {
//I have tried this, this causes the problem, even though it clears the data correctly
delete fSearchResultContainer;
//tried this, does nothing
QLayoutItem *child;
while ((child = fSearchResultsLayout->takeAt(0)) != 0) {
...
delete child;
}
}
void MyClass::populateWithSearchesults(std::vector<std::string> &aSearchItems) {
fSearchResultContainer = new QWidget();
fSearchResultContainer->setLayout(fSearchResultsLayout);
for (int rowNum = 0; rowNum < aSearchItems.size(); rowNum++) {
QHBoxLayout *row = new QHBoxLayout();
//populate the row with some widgets, all allocated through 'new', without specifying any parent, like
QPushButton *loc = new QPushButton("Foo");
row->addWidget(loc);
fSearchResultsLayout->addLayout(row, rowNum, 0,1,2);
}
fResultsViewBox->setWidget(fSearchResultContainer);
}
问题是,当我调用内部调用 delete
的 onClear
时,它会删除所有显示的结果。但在那之后,如果我再次调用 populateWithSearchesults
,我的应用程序就会崩溃,并且堆栈跟踪显示此方法是崩溃的地方。
我该如何解决这个问题?
看来你对所有权有一些误解。 QLayout
获得添加到它的任何项目的所有权:http://doc.qt.io/qt-5/qlayout.html#addItem
这意味着 QLayout
负责删除这些项目。如果您删除它们,那么 QLayout
也会尝试删除它们,然后您就会遇到现在看到的崩溃。
QLayout
没有很好的删除内容和重新添加内容的功能(例如 removeWidget
可能不会像您希望的那样工作。)但这是有原因的。
QLayout
不适用于列表视图。
你想要的是一个,等等,QListView
。它甚至可以为您处理滚动功能,和 使添加和删除元素成为可能。
实际上你可以轻松解决这个问题,即使你使用 QGridLayout
或任何其他 Layout
s :
subLayout->removeWidget(m_visibleCheckBox);//removes and then it causes some zigzag drawing at (0,0)
m_visibleCheckBox->setVisible(false);//asks to redraw the component internally
setLayout(subLayout);//for safety as we may use that layout again and again
如果你只使用第一行,它会导致:
我有一段代码可以执行此操作:名为 prepareUI
的方法使 UI 准备好加载输入的搜索结果。当需要清除已经显示的结果时调用名为 onClear
的方法。还有一个名为 populateSearchResults
的方法,它获取搜索数据并用它加载 UI。保存数据的容器是一个公开可用的指针,因为它需要清除 onClear
:
void MyClass::prepareSearchUI() {
//there may be many search results, hence need a scroll view to hold them
fResultsViewBox = new QScrollArea(this);
fResultsViewBox->setGeometry(28,169,224,232);
fSearchResultsLayout = new QGridLayout();
}
void MyClass::onClear() {
//I have tried this, this causes the problem, even though it clears the data correctly
delete fSearchResultContainer;
//tried this, does nothing
QLayoutItem *child;
while ((child = fSearchResultsLayout->takeAt(0)) != 0) {
...
delete child;
}
}
void MyClass::populateWithSearchesults(std::vector<std::string> &aSearchItems) {
fSearchResultContainer = new QWidget();
fSearchResultContainer->setLayout(fSearchResultsLayout);
for (int rowNum = 0; rowNum < aSearchItems.size(); rowNum++) {
QHBoxLayout *row = new QHBoxLayout();
//populate the row with some widgets, all allocated through 'new', without specifying any parent, like
QPushButton *loc = new QPushButton("Foo");
row->addWidget(loc);
fSearchResultsLayout->addLayout(row, rowNum, 0,1,2);
}
fResultsViewBox->setWidget(fSearchResultContainer);
}
问题是,当我调用内部调用 delete
的 onClear
时,它会删除所有显示的结果。但在那之后,如果我再次调用 populateWithSearchesults
,我的应用程序就会崩溃,并且堆栈跟踪显示此方法是崩溃的地方。
我该如何解决这个问题?
看来你对所有权有一些误解。 QLayout
获得添加到它的任何项目的所有权:http://doc.qt.io/qt-5/qlayout.html#addItem
这意味着 QLayout
负责删除这些项目。如果您删除它们,那么 QLayout
也会尝试删除它们,然后您就会遇到现在看到的崩溃。
QLayout
没有很好的删除内容和重新添加内容的功能(例如 removeWidget
可能不会像您希望的那样工作。)但这是有原因的。
QLayout
不适用于列表视图。
你想要的是一个,等等,QListView
。它甚至可以为您处理滚动功能,和 使添加和删除元素成为可能。
实际上你可以轻松解决这个问题,即使你使用 QGridLayout
或任何其他 Layout
s :
subLayout->removeWidget(m_visibleCheckBox);//removes and then it causes some zigzag drawing at (0,0)
m_visibleCheckBox->setVisible(false);//asks to redraw the component internally
setLayout(subLayout);//for safety as we may use that layout again and again
如果你只使用第一行,它会导致: