这似乎并不容易.基本上,我通过函数将QPushButtons添加到布局中,当函数执行时,我想首先清除布局(删除所有QPushButtons以及其中的任何其他内容),因为更多按钮只会附加到滚动视图.
头
QVBoxLayout* _layout;
CPP
void MainWindow::removeButtonsThenAddMore(const QString &item) {
//remove buttons/widgets
QVBoxLayout* _layout = new QVBoxLayout(this);
QPushButton button = new QPushButton(item);
_layout->addWidget(button);
QPushButton button = new QPushButton("button");
_layout->addWidget(button);
QWidget* widget = new QWidget();
widget->setLayout(_layout);
QScrollArea* scroll = new QScrollArea();
scroll->setWidget(widget);
scroll->show();
}
Tee*_*sti 42
我有同样的问题:我有一个游戏应用程序,其主窗口类继承QMainWindow.它的构造函数看起来部分如下:
m_scene = new QGraphicsScene;
m_scene->setBackgroundBrush( Qt::black );
...
m_view = new QGraphicsView( m_scene );
...
setCentralWidget( m_view );
当我想显示游戏关卡时,我实例化一个QGridLayout,我在其中添加QLabel,然后将它们的像素图设置为某些图片(带有透明部分的pixmaps).第一级显示正常,但是当切换到第二级时,第一级的像素图仍然可以在新的像素图后面看到(像素图是透明的).
我尝试了几件事来删除旧的小部件.(a)我尝试删除QGridLayout并实例化一个新的,但后来了解到删除布局不会删除添加到它的小部件.(b)我尝试在新的pixmaps上调用QLabel :: clear(),但这当然只会影响新的像素,而不会影响僵尸.(c)我甚至尝试删除我的m_view和m_scene,并在每次显示新级别时重建它们,但仍然没有运气.
然后(d)我尝试了上面给出的解决方案之一,即
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
    delete wItem;
但这也行不通.
然而,谷歌搜索进一步,我找到了一个有效的答案.(d)遗漏的是打电话给delete item->widget().以下现在对我有用:
// THIS IS THE SOLUTION!
// Delete all existing widgets, if any.
if ( m_view->layout() != NULL )
{
    QLayoutItem* item;
    while ( ( item = m_view->layout()->takeAt( 0 ) ) != NULL )
    {
        delete item->widget();
        delete item;
    }
    delete m_view->layout();
}
然后我像第一级一样实例化一个新的QGridLayout,向它添加新级别的小部件,等等.
Qt在很多方面都很棒,但我认为这些问题表明这里的事情可能会更容易一些.
Dar*_*vic 38
Qt帮助中的布局管理页面说明:
布局将自动重新显示窗口小部件(使用QWidget :: setParent()),以便它们是安装布局的窗口小部件的子窗口.
我的结论:小部件需要手动销毁或通过销毁父WIDGET而不是布局来销毁
布局中的窗口小部件是安装布局的窗口小部件的子窗口,而不是布局本身.窗口小部件只能将其他窗口小部件作为父窗口,而不是布局.
我的结论:同上
致@Muelner的"矛盾""项目的所有权转移到布局,布局的责任是删除它." - 这并不意味着WIDGET,而是重新布局的ITEM,稍后将被布局删除.窗口小部件仍然是安装布局的窗口小部件的子窗口,需要手动删除它们或删除整个父窗口小部件.
如果一个人真的需要从布局中删除所有小部件和项目,让它完全为空,他需要创建一个递归函数,如下所示:
// shallowly tested, seems to work, but apply the logic
void clearLayout(QLayout* layout, bool deleteWidgets = true)
{
    while (QLayoutItem* item = layout->takeAt(0))
    {
        if (deleteWidgets)
        {
            if (QWidget* widget = item->widget())
                widget->deleteLater();
        }
        if (QLayout* childLayout = item->layout())
            clearLayout(childLayout, deleteWidgets);
        delete item;
    }
}
m.w*_*.w. 12
我知道这个问题很老并且已经回答了,但是:由于QtAlgorithms提供了qDeleteAll,因此可以删除布局,包括使用单行删除所有子代.此代码删除布局,其所有子项以及布局内的所有内容都"消失".
qDeleteAll(yourWidget->children());
以下是重载函数的说明:
void qDeleteAll(ForwardIterator begin,ForwardIterator end)
使用C++ delete>运算符删除[begin,end]范围内的所有项目.项类型必须是指针类型(例如,QWidget*).
请注意,qDeleteAll需要从该窗口小部件(而不是该布局)提供容器.请注意,qDeleteAll不会删除QtAlgorithms- 只是它的子项.
现在可以设置新的布局.
未尝试:为什么不创建新布局,将其与旧布局交换并删除旧布局?这应该删除布局所拥有的所有项目并保留其他项目.
编辑:在研究了我的答案,文档和Qt源代码的评论后,我发现了一个更好的解决方案:
如果你仍然启用了Qt3支持,你可以使用QLayout :: deleteAllItems(),这与QLayout :: takeAt的文档中的提示基本相同:
以下代码片段显示了从布局中删除所有项目的安全方法:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
  ...
  delete child;
}
编辑:经过进一步的研究,看起来上面的两个版本都是等价的:只有子布局和没有父项的小部件被删除.父母的小部件以特殊方式处理.看起来TeL的解决方案应该可行,您应该注意不要删除任何顶级小部件.另一种方法是使用窗口小部件层次结构删除窗口小部件:创建一个没有父窗口的特殊窗口小部件,并创建所有可移动窗口小部件作为此特殊窗口小部件的子窗口.清理布局后删除此特殊小部件.
您还需要确保删除间隔器和不是 QWidget 的东西。如果您确定布局中唯一的东西是 QWidgets,那么前面的答案就可以了。否则你应该这样做:
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
      delete wItem;
了解如何执行此操作很重要,因为如果您要清除的布局是更大布局的一部分,则您不想破坏该布局。您希望确保您的布局保持其位置以及与窗口其余部分的关系。
您还应该小心,每次调用此方法时都会创建大量对象,并且不会清除它们。首先,您可能应该在其他地方创建 QWidget 和 QScrollArea,并保留一个指向它们的成员变量以供参考。那么您的代码可能如下所示:
QLayout *_layout = WidgetMemberVariable->layout();
// If it is the first time and the layout has not been created
if (_layout == 0)
{
  _layout = new QVBoxLayout(this);
  WidgetMemberVariable->setLayout(_layout);
}
// Delete all the existing buttons in the layout
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
    delete wItem;
//  Add your new buttons here.
QPushButton button = new QPushButton(item);
_layout->addWidget(button);
QPushButton button = new QPushButton("button");
_layout->addWidget(button);
如果你想删除所有小部件,你可以这样做:
foreach (QObject *object, _layout->children()) {
  QWidget *widget = qobject_cast<QWidget*>(object);
  if (widget) {
    delete widget;
  }
}
| 归档时间: | 
 | 
| 查看次数: | 58522 次 | 
| 最近记录: |