C++ 如何在Qt中从布局中删除小部件

C++ 如何在Qt中从布局中删除小部件,c++,qt,pointers,qlayout,C++,Qt,Pointers,Qlayout,我有一段代码可以做到这一点:一个名为prepareUI的方法使UI准备好加载输入到其中的搜索结果。一种名为onClear的方法,当已经显示的结果需要清除时调用该方法。还有一个名为的方法populateSearchResults,它获取搜索数据并加载UI。保存数据的容器是一个公开可用的指针,因为需要它来清除onClear中的结果: void MyClass::prepareSearchUI() { //there may be many search results, hence

我有一段代码可以做到这一点:一个名为
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);
}
void MyClass::prepareSearchUI(){
//可能有许多搜索结果,因此需要滚动视图来保存它们
fResultsViewBox=新的QScrollArea(本);
fResultsViewBox->setGeometry(28169224232);
fSearchResultsLayout=新的QGridLayout();
}
void MyClass::onClear(){
//我尝试过这个,这导致了问题,即使它正确地清除了数据
删除fSearchResultContainer;
//试过了,什么也没做
QLayoutItem*子项;
while((child=fSearchResultsLayout->takeAt(0))!=0){
...
删除儿童;
}
}
void MyClass::populateWithSearchesults(std::vector和aSearchItems){
fSearchResultContainer=新的QWidget();
fSearchResultContainer->setLayout(fSearchResultsLayout);
对于(int-rowNum=0;rowNum添加小部件(loc);
fSearchResultsLayout->addLayout(行,行数,0,1,2);
}
fResultsViewBox->setWidget(fSearchResultContainer);
}
问题是,当我调用内部调用
delete
onClear
时,它确实会删除显示的所有结果。但是在那之后,如果我再次调用
populateWithSearchesults
,我的应用程序就会崩溃,堆栈跟踪显示这个方法崩溃的地方


如何解决此问题?

您似乎对所有权有一些误解。
QLayout
获取添加到其中的任何项目的所有权:

这意味着
QLayout
负责删除这些项目。如果您删除它们,那么
QLayout
也会尝试删除它们,然后您会看到现在出现的崩溃

QLayout
在删除内容和重新添加内容方面没有很好的功能(例如,可能无法像您希望的那样工作),但这是有原因的

QLayout
不打算用作列表视图


你想要的是一个,等等。它甚至可以为您处理滚动功能,并使添加和删除元素成为可能。

实际上,您可以轻松解决此问题,即使您使用的是
QGridLayout
或任何其他
布局:

    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
如果只使用第一行,将导致以下情况:


可能QListView可以正常工作,但我目前需要让它与QLayout一起工作。有指针吗?@Cupidvogel所以明确的答案是你必须使用
removeWidget
,然后你或者widget之前的任何所有者将清理它。然后,您需要调用
update
以及任何其他需要进行的调整,以使布局再次正确。让我再求你一次,“为了你,为了那些不得不看代码库的人,为了我这个讨厌犯错的人,请不要这样做。”好吧,那么,如果不听从你真诚的请求,那就太残忍了……)我将使用QListView。让我看看我如何才能做到这一点。@Cupidvogel你应该知道,我感到更快乐,世界更美好!Qt的
QListView
是它们最简单的
qabstractemview
,但是您仍然需要不时地深入到
SelectionModel
qabstractemodel
。这是一个你将在Qt中反复使用的范例,所以不要认为你在学习的过程中浪费了时间。在您开始使用时,可能会对您特别有用。如果你有问题,请在这里贴一个链接,我会来尝试回答。非常感谢!可以……)可能重复的