Deleting data from a QScrollArea
-
Hello!
I am having some trouble removing data from a QScrollArea. When I load data into my GUI, I can school and everything is fine. When I load another set of data, however, my GUI adjusts it's scroll area to match that of the new file but doesn't get rid of the old data. It just lays the new data on top of the old data, creating a neat effect but unwanted.
Here is my code:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); scrollArea = new QScrollArea(); scrollArea->setBackgroundRole(QPalette::Light); scrollArea->setWidgetResizable(true); mainVbox = new QVBoxLayout(); myWidget = new QWidget(); myWidget->setLayout(mainVbox); scrollArea->setWidget(myWidget); setCentralWidget(scrollArea); }
So I create my QScrollArea, change some of it's attributes.
Next I create a widget to hold my main layout.
Then I set the widget ofscrollArea
tomyWidget
.
Lastly, I set the central widget toscrollArea
.What I add to the mainLayout is another layout that contains three widgets. And I add a LOT of these layouts to the main layout. Here is that code with the code I thought would delete the old layouts
... ... QLayoutItem* child; while((child = myWidget->layout()->layout()->takeAt(0)) != NULL) { delete child->layout()->widget(); //This doesn't work but it doesn't break anything... } for(int counter = 0; counter < orderQ.size(); counter++) { subHbox = new QHboxLayout; if(orderQ.at(counter) == 0) { Qlabel *label = new QLabel(); ... ... mainVbox->addLayout(subHbox); } else if(...) { ... mainVbox->addLayout(subHbox); ... }
Any help or ideas would be greatly appreciated.
Thank you!!
-
Hi
I was wondering why you cannot just delete
myWidget as that would/should delete all childs also.
Then make new "myWidget" and fill it again. -
Thank you for your reply!
I tried deleting
myWidget
and no matter what I did, it crashed every time. But that got me thinking of other ways to approach this. So I did some more thinking and searching, and found in the docs this.I tried
QList<QLayout *> allSubLayouts = mainVbox->findChildren<QLayout *>(); if(!allSubLayouts.empty()) { int size = allSubLayouts.size(); for(int i = 0; i < size; i++) { delete allSubLayouts.at(i); } }
that produced no results but maybe just deleting the layout only removes the layout. So I tried deleting the widgets in those layouts before deleting the layouts.
if(!allSubLayouts.empty()) { int size = allSubLayouts.size(); QLayoutItem *child; qDebug() << "***************The layout list was not empty" ; for(int i = 0; i < size; i++) { while((child = allSubLayouts.at(i)->takeAt(0)) != 0) { qDebug() << "deleting CHILD " << child; delete child; } qDebug() << "deleting layout " << i << " that has memory address " << allSubLayouts.at(i); delete allSubLayouts.at(i); } mainVbox->update(); myWidget->update(); }
As you can see I also tried updating the main layout as well as the widget to no avail. The debug printout says that it is making it into the loop and accessing the correct number of widgets and layouts. I'm just not sure of what to do right now.
-
Hmm.
Ok. I was kinda planning
to just create new widget with a boxlayout and call
setWidget on ScrollArea.
But u say this crashes? -
Hi again
i made same layout in designer
I kill them this wayvoid MainWindow::on_btremove_released() { QList<QWidget*> allSubLayouts = ui->innerwidget->findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly); int size = allSubLayouts.size(); // take all out while (( ui->innerwidget->layout()->takeAt(0)) != 0) // killem for(int i = 0; i < size; i++) { qDebug() << allSubLayouts[i]->metaObject()->className(); delete allSubLayouts[i]; } }
U can check your self.
https://www.dropbox.com/s/auivviiv8tv7jfw/myscroll.zip?dl=0
should be the same you want if i read ur fine drawing correct :)
Note the Qt::FindDirectChildrenOnly flag! -
@mrjj
I don't want to delete my QWidget because I would have to dynamically create a new one each time I loaded a new file and I really don't want to deal with that.I'm making some progress with this:
while((child = mainVbox->layout()->takeAt(0)) != 0) { delete child; }
but in the documentation it says that when I delete a layout, I have to delete the widgets separately.
So I'm trying to make a list of the widgets found within the sublayout and then delete from there but it's not working. -
Did u try the sample?
It leaves the QWidget and layout but kills all it members. -
Hi
In the documentation for findChildren. I went looking as your
drawing made it very clear what u wanted. (kill all inner widgets)So If you do it for your Widget (myWidget), it should do the same.
( i hope :)you are welcome. I hope u get it to work.
-
@mrjj
So here is what I've ended up doing.I had been able to get a QList of the layouts in the main layout like so
QList<QLayout *> allSubLayouts = mainVbox->findChildren<QLayout *>();
So I checked if that list was empty or not, basically seeing if it was the first time to use the program.
if(!allSubLayouts.empty()) { int size = allSubLayouts.size(); for(int i = 0; i < size; i ++) { qDebug() << "this is what is at allSublayouts.at("<<i<<") " << allSubLayouts.at(i); for(int j = 0; j < allSubLayouts.at(i)->count(); ++j) { QWidget *w = allSubLayouts.at(i)->itemAt(j)->widget(); if(w != NULL) { w->setVisible(false); } } } }
Since I knew that there were layouts available, instead of using
findChildren()
I usedallSubLayouts.at(i)->*itemAt*(j)->*widget*();
While this solves my problem of widgets and layouts overlapping in MainWindow, I don't know if it will cause a memory leak or will use up too much memory, since I'm not deleting any widgets/layouts.
-
Hi
"allSubLayouts.at(i)->*itemAt*(j)->*widget*();"
made my brain hurt :)
Well since u are not deleting any widgets, u will use more and more memory,
but since they are still owned by layout, it will be free when application ends.