• 32154阅读
  • 22回复

如何动态删除QGridLayout里的控件 [复制链接]

上一主题 下一主题
离线alexltr
 

只看楼主 倒序阅读 楼主  发表于: 2010-12-08
— 本帖被 XChinux 执行加亮操作(2011-01-10) —
我在QGridLayout里添加了很多QPushButton。
请问如何在运行时将这些PushButton全部删除

我用removeItem试了很久都不行,请各位指点一下。谢谢。

void SizeLayout::removeAllButtons()
{
    while(sizeLayout->count()>0)
    {
        sizeLayout->removeItem(0);
    }
}
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线roywillow

只看该作者 1楼 发表于: 2010-12-08
感觉应该是removeWidget(),并且需要传递移除的widget的指针,而不是0
还有一些细节的东西最好参考一下assistant
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线alexltr

只看该作者 2楼 发表于: 2010-12-11
试了几天了都不行,大家帮帮我吧!!!

以下这个是跟assitant做的,也不行。
void SizeLayout::removeAllButtons()
{
    QLayoutItem *sizeBtn;
    while((sizeBtn=sizeLayout->takeAt(0)) !=0)
    {
        delete sizeBtn;
    }
}

以下这种方法加以下测试语句(已注释掉)后可以看到被删除的效果,但最后一个控件无法删除。
但如果注释掉以下两句语句,就看不到任何反应了。
void SizeLayout::removeAllButtons()
{
    while(sizeLayout->count())
    {
        //QString num;
        //QMessageBox::information(this,"test",num.setNum(sizeLayout->count()));
        sizeLayout->removeItem(sizeLayout->itemAt(0));
    }
}

我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线alexltr

只看该作者 3楼 发表于: 2010-12-11
终于找到了!!! 用以下语句可以达到我要的效果。
但这样只是隐藏起来,不知是否有问题。

sizeLayout->itemAt(i)->widget()->hide()
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线cofei
只看该作者 4楼 发表于: 2011-01-07
得到每个ITEM , 先把每个item的parent设为0,再delete掉
离线alexltr

只看该作者 5楼 发表于: 2011-01-09
Thank you very much, cofei.
想不到过了这么久还有人帮我,谢谢!!!

其实我一直觉得我的程序有问题,因为程序越运行所占的内存越大。可能是LAYOUT里面的控件越来越多。虽然隐藏了,但无法删除。我再用用cofei的方法试一下。
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线alexltr

只看该作者 6楼 发表于: 2011-01-09
用Cofei的方法可以删除控件,不用hide()函数了。
但程序还是越运行所占的内存越大,找了很久不知是什么原因。
这个小程序的功能主要是根据不同的选项用PushButton在Layout中显示不同内衣的等码表。每显示一次前先将前一次显示的PushButton全部删掉。程序的主要代码如下:
void SizeLayout::showSizeLayout()
{
    setViewType();
    removeAllSizes();
    setSizeFont();

    int rowSpeed=rowSpeedSpin->value();
    int columnSpeed=columnSpeedSpin->value();
    QPalette pal=palette();
    pal.setColor(QPalette::ButtonText,Qt::blue);

    for(int row=0; row<cupRange.count(); row++)
    {
        for(int column=0; column<bandRange.count(); column++)
        {
            QPushButton *sizeButton = new QPushButton(tr("%1%2")
                        .arg(bandRange.value(column)).arg(cupRange.value(row)),this);
            sizeButton->setPalette(pal);
            //sizeButton->setStyleSheet ("background-color: rgb(180,180,180);color: rgb(15,15,15);");
            sizeLayout->addWidget(sizeButton,row,column+row);
            sleep(columnSpeed);
        }
        sleep(rowSpeed);
    }
}

void SizeLayout::removeAllSizes()
{
    QLayoutItem *sizeBtn;
    while((sizeBtn=sizeLayout->takeAt(0)) !=0)
    {
        sizeBtn->widget()->setParent(0);
        delete sizeBtn;
    }
}
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
只看该作者 7楼 发表于: 2011-01-10
删除方法不对.

gridlayout->removeWidget(gridlayout->itemAt(x)->widget());
离线alexltr

只看该作者 8楼 发表于: 2011-01-10
引用第7楼算了不说了于2011-01-10 11:12发表的 :
删除方法不对.
gridlayout->removeWidget(gridlayout->itemAt(x)->widget());


已测试过,单用此法无法真正删除。还是显示在layout里.
还是要用4楼cofei的方法才可以真正从视觉上删除掉。

但内存占用问题还是没有解决,还是会越来越大。

void SizeLayout::removeAllSizes()
{
QLayoutItem *sizeBtn;
while((sizeBtn=sizeLayout->takeAt(0)) !=0)
{
sizeLayout->removeWidget(sizeBtn->widget());
sizeBtn->widget()->setParent(0);
delete sizeBtn;
}
}
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线alexltr

只看该作者 9楼 发表于: 2011-01-11
现在我上传所有的代码,请大家多多指点。试看是否可以找出内存问题的所在。

这是我的第一个QT小程序,没有什么实际应用功能。是边学边写的,主要是应用和检验自己所学的内容。
开头的构造函数可能有点臃肿,按道理应该分开几个SLOT写的。
附件: Qprj025.rar (6 K) 下载次数:31
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线jdwx

只看该作者 10楼 发表于: 2011-01-11
是不是可以考虑用对话框,或者用其它的控件和方法。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线alexltr

只看该作者 11楼 发表于: 2011-01-12
引用第10楼jdwx于2011-01-11 21:39发表的 :
是不是可以考虑用对话框,或者用其它的控件和方法。


用对话框也许可以吧。但这好像不符合我的要求,感觉不好看。
而且我还是想知道我的方法为什么不行? 毕竟学习嘛。
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线cycloneii

只看该作者 12楼 发表于: 2011-01-12
至于这么麻烦吗?我写了一个很简单的测试程序,上面是3x3的qpushbotton矩阵,下面是一个qcombox和一个qpushbutton,从qcombox里面可以选择删除哪一个qpushbutton,如果为空,表示删除全部,按下delete按键,开始删除,没有任何问题,附上代码如下
gridlayouttest.tar.gz (3 K) 下载次数:80   
离线cycloneii

只看该作者 13楼 发表于: 2011-01-12
其实没有必要每次判断gridlayout是否还有子对象,直接用findchildren之类的函数,一次性的找到所有的子对象,然后用遍历整个子对象队列,删除该子对象即可
离线alexltr

只看该作者 14楼 发表于: 2011-01-12
我现在的问题不是单单是怎样删除layout里面的pushbutton.
里面的pushbuttons的排列是表示某种等量关系的图示,程序的使用者可以根据不同的选项显示不同的图示。
也就是说,删除原有的pushbuttons后,还要重新产生新的pushbuttons来排列出新的图示。
而在这个过程中,程序运行所占的内存却越来越大,直到使用者关闭程序才释放内存。这才是问题的所在。

而你的程序只解决了如何删除的问题。Thank you anyway.

我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线cycloneii

只看该作者 15楼 发表于: 2011-01-13
引用第14楼alexltr于2011-01-12 22:58发表的  :
我现在的问题不是单单是怎样删除layout里面的pushbutton.
里面的pushbuttons的排列是表示某种等量关系的图示,程序的使用者可以根据不同的选项显示不同的图示。
也就是说,删除原有的pushbuttons后,还要重新产生新的pushbuttons来排列出新的图示。
而在这个过程中,程序运行所占的内存却越来越大,直到使用者关闭程序才释放内存。这才是问题的所在。
.......


你把removeAllSizes()改成我的删除方式就可以避免内存泄露了
代码也给你吧,我做过测试了
void SizeLayout::removeAllSizes()
{
    QList<QPushButton*> items = sizeBox->findChildren<QPushButton*>(QString());
    foreach(QPushButton*item, items)
    {
        delete item;
    }
}
Qprj025.tar.gz (5 K) 下载次数:115
离线alexltr

只看该作者 16楼 发表于: 2011-01-13
Hi cycloneii. 按照你的方法可以解决这个内存问题了!非常感谢。

但我有一个疑问,为什么是找sizeBox的children呢?
我把sizeBox改成sizeLayout,用同样的方法,却不能成功删除,而且还是有内存问题。
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线cycloneii

只看该作者 17楼 发表于: 2011-01-13
引用第16楼alexltr于2011-01-13 22:21发表的  :
Hi cycloneii. 按照你的方法可以解决这个内存问题了!非常感谢。
但我有一个疑问,为什么是找sizeBox的children呢?
我把sizeBox改成sizeLayout,用同样的方法,却不能成功删除,而且还是有内存问题。

layout是需要一个QWidget作为容器的,所有加入layout中的控件都是对应容器的子控件,因此从容器中查找子控件,然后删除是最合适的方法。你原来删除的是QLayoutItem,不是QPushButton,所以有内存泄露,也就是说你只是把QPushButton从layout里面移除了,所以它不显示,但是并不代表这个QPushButton被完全删除了
1条评分金钱+5
长桥卧雪 金钱 +5 非常感谢! 2018-02-09
离线alexltr

只看该作者 18楼 发表于: 2011-01-13
Re:如何动态删除QGridLayout里的控件(已解决)
非常感谢cycloneii详尽的解释,我现在明白了。
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线myseemylife

只看该作者 19楼 发表于: 2012-01-04
用遍历子控件的方法可以删除。。。但是界面上的还在。。。除非把控件delete
。。。。下次显示的时候又需要再new一遍。。真是麻烦
蠢笨的愚钝~
离线byron1655

只看该作者 20楼 发表于: 2014-02-08
好帖,收藏了
离线xxisj

只看该作者 21楼 发表于: 2017-03-06
非常感谢楼主和cycloneii,我的项目正需要这个功能,你们帮了大忙,感谢你们的无私分享,敬礼!!
离线js_gary

只看该作者 22楼 发表于: 2019-10-29
8年前的问题,结果是实现了,但问题在layout里为什么不能删除,似乎还没说清楚,我提供一个方法,似乎可以达到同样的效果。
    QLayoutItem *item;
    while((item = ui->gridLayout->takeAt(0)) != 0){
        if(item->widget()){
            ui->gridLayout->removeWidget(item->widget());
            item->widget()->setParent(0);
            delete item->widget();
        }
        delete item;
    }
快速回复
限100 字节
 
上一个 下一个