如何在Qt中从布局中移除小部件

3
我有一段代码,其中有三个方法与此相关:一个名为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);
}

问题是,当我调用onClear时,其内部调用delete,它确实删除了所有显示的结果。但在此之后,如果我再次调用populateWithSearchesults,我的应用程序会崩溃,并且堆栈跟踪将此方法显示为发生崩溃的位置。
我该如何解决这个问题?

2个回答

4
看起来您对所有权有一些误解。一个QLayout将拥有添加到其中的任何项目:http://doc.qt.io/qt-5/qlayout.html#addItem 这意味着QLayout负责删除这些项目。如果您删除它们,那么QLayout也会尝试删除它们,然后您就会看到现在出现的崩溃。
QLayout没有很好的功能来删除内容并重新添加它们(例如removeWidget可能不像您希望的那样工作)。但是这有原因。
QLayout不打算用作列表视图。
您需要的是,等待它,QListView。它甚至会为您处理滚动功能,并使添加和删除元素成为可能。

也许 QListView 可以使用,但我目前需要将其与 QLayout 结合使用。有什么指针吗? - SexyBeast
@Cupidvogel 所以明确的答案是,你必须使用 removeWidget 然后你或者之前的所有者将清理它。然后你需要调用 update 和其他必要的调整来使布局再次看起来正确。让我再次恳求你一次,“请不要这样做,为了你自己,为了其他任何需要查看代码库的人,也为了我这个讨厌做错事情的人。” - Jonathan Mee
1
好的,不理会你真诚的请求是很残忍的.. :) 我将使用 QListView。让我看看如何使其工作.. - SexyBeast
@Cupidvogel 你应该知道,我感觉更快乐了,世界变得更美好了!Qt的QListView是他们最简单的QAbstractItemView之一,但有时仍需要涉及到SelectionModelQAbstractItemModel。这是在Qt中反复使用的范例,所以不要认为你在学习时浪费了时间。这个例子对你入门会非常有用。如果你在学习过程中有问题,请在此处发布链接,我会来尽力回答。 - Jonathan Mee
非常感谢!我会去做的.. :) - SexyBeast
显示剩余2条评论

0

实际上,您可以轻松解决此问题,即使您正在使用 QGridLayout 或任何其他 Layout

    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

如果你只使用第一行,会导致这个问题:

qt removeWidget best way


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接