Results 1 to 15 of 15

Thread: QStackedWidget and memory management

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default QStackedWidget and memory management

    I'm trying to implement a stack solution in my application so I can push and pop widgets into the stack. I'm using a QStackedWidget. When a widget is removed from the stack I want to make sure that it is also deallocated. In my code below will the pageWidget get deleted and deallocated when I run removeWidget()? Or will it be deleted when stackedWidget is deleted? How can I make it get deleted when it is removed from the stackedWidget?

    Qt Code:
    1. QStackedWidget *stackedWidget = new QStackedWidget(this);
    2. QWidget *pageWidget = new QWidget(stackedWidget);
    3. stackedWidget->addWidget(pageWidget);
    4.  
    5. //Will this delete this pageWidget and deallocate memory?
    6. stackedWidget->removeWidget(pageWidget);
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QStackedWidget and memory management

    Well the documentation is clear on that:
    Note: The ownership of widget remains the same. The widget is not deleted, but simply removed from the widget's stacked layout, causing it to be hidden.
    So you have to do it yourself:
    Qt Code:
    1. stackedWidget->removeWidget(pageWidget);
    2. pageWidget->deleteLater(); // or: delete pageWidget;
    To copy to clipboard, switch view to plain text mode 

  3. The following user says thank you to Lykurg for this useful post:

    martinn (29th March 2010)

  4. #3
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Aha, must have missed that! :-) So using deleteLater will delete the widget as soon it is removed from stackedWidget and not is visible? Or will it still need stackedWidget to get deleted before widget gets deleted (as stackedWidget is the parent)?

  5. #4
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QStackedWidget and memory management

    deleteLater has nothing to do with your stacked widget. By calling stackedWidget->removeWidget(widget), widget is removed from the stacked widget and is not visible any more. Then you have free the memory by calling delete. That's the normal way. deleteLater ist just a little bit saver, but behaves like delete, only that "delete" is called on the widget after control returns to the event loop. Compare:
    Qt Code:
    1. void Class::function()
    2. {
    3. //...
    4. delete widget;
    5. int i = widget->getSomeInt(); // this will crash your app!
    6. delete widget; // invalide
    7. }
    8.  
    9. void Class::function()
    10. {
    11. //...
    12. widget->deleteLater();
    13. int i = widget->getSomeInt(); // this will NOT crash your app!
    14. widget->deleteLater(); // possible
    15. }
    To copy to clipboard, switch view to plain text mode 

  6. #5
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Yes, I think I understand. But when testing my application I can't see the memory get released it keeps growing. To be totally sure that I understand right I'll try and explain my solution:

    My application is built on a stack solution looking like this:

    I have one QStackedWidget. The first widget in the QStackedWidget is a kind of home screen. It has a list of categories. When the user clicks a category a new widget is added to the QStackedWidget with a list of sub categories. If the user clicks a sub category a new widget is added with a new list. There are some steps of sub categories until a widget shows where the user can edit items. When the user have saved the changes of an item he get sent back to the home screen and all the other widgets should get deleted from the stack.

    It should look something like this:

    Home screen->Categories->Categories->Items->Edit Item->Save---->
    <-----------------back to home screen, delete all widgets------------

    Qt Code:
    1. //To create the QStackedWidget and add the "home screen"
    2. QStackedWidget *stackedWidget = new QStackedWidget(this);
    3. QWidget *homescreenWidget = new QWidget(this);
    4. stackedWidget->addWidget(homescreenWidget);
    5. stackedWidget->setCurrentWidget(homescreenWidget);
    6.  
    7. //When the user clicks a category in the list (this is made each time a category in the list is clicked)
    8. QWidget *categoryListWidget = new QWidget(this);
    9. stackedWidget->addWidget(categoryListWidget);
    10. stackedWidget->setCurrentWidget(categoryListWidget);
    11.  
    12. //When the user has saved the changes to an item he should be sent back to home screen
    13. //All items except home screen should be removed from stackedWidget and deleted from memory
    14. stackedWidget->setCurrentWidget(stackedWidget->widget(0));
    15. for(int i = stackedWidget->count(); i>0; i--){
    16. QWidget* widget = stackedWidget->widget(i);
    17. stackedWidget->removeWidget(widget);
    18. widget->deleteLater();
    19. }
    To copy to clipboard, switch view to plain text mode 

  7. #6
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QStackedWidget and memory management

    First you should reconsider your approach. Why do you do not reuse the widgets? I think it is better than permanent creating and removing. But anyway.

    try to use delete and see what the memory is telling you. I guess the same. What tool do you use of measuring the memory usage? And then, the application (or better the system) frees the memory but kept it allocated with the application. So the memory is freed but in the "memory watching tool" it seems that is doesn't.

  8. #7
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    I'm running the Symbian Emulator with Carbide C++, and in Diagnostics I can see the memory increasing and after maybe 4-5 times of clicking down in my solution and editing items, my app craches. The same thing happens if I run on the Nokia 5800 device, after some time I get a memory warning. I can understand this, it makes totally sense as the widgets parent never gets deleted and therefore neither the widgets, so for each time I click down in the solution more widgets are created.

    What would be a better solution then using this way, how could I reuse the widgets? My approach is taken from http://www.forum.nokia.com/info/sw.n...t_Example.html In their code they don't use delete anywhere, maybe I shouldn't need that either but am doing something wrong. In the code in the nokia example I tried adding widget->deleteLater() in QBaseWidget after removing the widget from the stackedwiget but that crashes the application.

    I'm not really sure how to solve this as adding widget->deleteLater() when deleting widget from stack widget craches the application and if I don't delete it I will get problem with memory. Any ideas?
    Last edited by martinn; 30th March 2010 at 15:57.

  9. #8
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Anyone have an idea on how to solve this?

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QStackedWidget and memory management

    You still didn't say what exactly is the problem. Of course we can try to guess how your code looks like but it would probably be easier if you just shew it to us.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #10
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Okey, its quite a large mess of code. But I'll make a smaller project that shows the problem and post it here asap. Thanks!

  12. #11
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Ok this is going to be quite a long post:

    I'm building an application for Qt for Symbian. Like I said before the idea of my application is built on a stack solution looking like this: I have one stacked widget. The first widget in the stacked widget is a kind of home screen. It has a list of categories. When the user clicks a category a new widget is added to the stacked widget with a list of sub categories. If the user clicks a sub category a new widget is added with a new list. The user clicks through the lists, and these steps can differ depending on user choices on the way. So the same widgets maybe wont be added in the same order each time. At last a widget shows where the user can edit items. When the user have saved the changes of an item he get sent back to the home screen and all the other widgets should get deleted from the stack.

    It should look something like this:

    Home screen->Categories->SOME STEPS->Items->Edit Item->Save---->
    <-----------------back to home screen, delete all widgets------------

    To be able to solve this I have subclassed QStackedWidget with my own CustomStackedWidget. The CustomStackedWidget can insert new widgets into the stack, remove them, and pop back to the home screen. This is my CustomStackedWidget:

    CustomStackedWidget.h:
    Qt Code:
    1. class CustomStackedWidget : public QStackedWidget
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. CustomStackedWidget(QWidget *parent);
    7. virtual ~CustomStackedWidget();
    8.  
    9. //Pops the stack
    10. virtual void popTo(int index);
    11.  
    12. // Activates existing view
    13. virtual void activateWidget(QWidget* widgetToFind);
    14.  
    15. // Removes view
    16. virtual void removeWidgetWithWidget(QWidget* widget);
    17.  
    18. // Activates new view.
    19. virtual void activateNewWidget(QWidget* newWidget);
    20.  
    21. public slots:
    22.  
    23. // Activates previous view and deletes current
    24. virtual void activatePreviousView();
    25.  
    26. };
    To copy to clipboard, switch view to plain text mode 

    CustomStackedWidget.cpp:
    Qt Code:
    1. #include "CustomStackedWidget.h"
    2.  
    3. CustomStackedWidget::CustomStackedWidget(QWidget *parent)
    4. : QStackedWidget(parent)
    5. {
    6.  
    7. }
    8.  
    9. CustomStackedWidget::~CustomStackedWidget()
    10. {
    11. // TODO Auto-generated destructor stub
    12. }
    13.  
    14. void CustomStackedWidget::popTo(int index){
    15. this->setCurrentWidget(this->widget(index));
    16. for(int i = this->count(); i > index; i--){
    17. QWidget* widget = this->widget(i);
    18. this->removeWidgetWithWidget(widget);
    19. }
    20. }
    21.  
    22. void CustomStackedWidget::activateWidget(QWidget* widgetToFind){
    23. for (int i=0; i < this->count(); i++)
    24. {
    25. QWidget* widget = this->widget(i);
    26. if (widget == widgetToFind)
    27. {
    28. this->setCurrentWidget(widget);
    29. break;
    30. }
    31. }
    32. }
    33.  
    34. void CustomStackedWidget::activateNewWidget(QWidget* newWidget){
    35. this->addWidget(newWidget);
    36. activateWidget(newWidget);
    37. }
    38.  
    39. void CustomStackedWidget::removeWidgetWithWidget(QWidget* widget)
    40. {
    41. this->removeWidget(widget);
    42. widget->deleteLater();
    43. }
    44.  
    45. void CustomStackedWidget::activatePreviousView()
    46. {
    47. QWidget *currentWidget = this->currentWidget();
    48. QWidget *previous;
    49.  
    50. for (int i=0; i < this->count(); i++)
    51. {
    52. QWidget* widget = this->widget(i);
    53. if (widget==currentWidget)
    54. {
    55. if (i>0)
    56. {
    57. i--;
    58. previous = this->widget(i);
    59.  
    60. // Remove current widget
    61. this->removeWidgetWithWidget(currentWidget);
    62.  
    63. // Activate previous widget
    64. activateWidget(previous);
    65. }
    66. break;
    67. }
    68. }
    69. }
    To copy to clipboard, switch view to plain text mode 

    Every widget that I insert into the stack is a sub class of my own widget MyWidget. To make it simple, in this example the UI of MyWidget just consist of one label showing which index in the stack the widget has. The UI also has one button to insert another widget, one button to remove the current widget and another one to pop to the first widget in the stack. This is just to show you the idea, in the real application the widget can have a lot of more stuff in it. This is MyWidget:

    MyWidget.h:
    Qt Code:
    1. class MyWidget : public QWidget
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. MyWidget(CustomStackedWidget *stackedWidget, QWidget *parent = 0);
    7. MyWidget(int index, CustomStackedWidget *stackedWidget, QWidget *parent = 0);
    8. ~MyWidget();
    9. CustomStackedWidget *stackedWidget;
    10. int index;
    11.  
    12. private:
    13. Ui::MyWidgetClass ui;
    14.  
    15. private slots:
    16. void on_pushButtonRemove_clicked();
    17. void on_pushButtonInsert_clicked();
    18. void on_pushButtonPop_clicked();
    19.  
    20. };
    To copy to clipboard, switch view to plain text mode 

    MyWidget.cpp:
    Qt Code:
    1. MyWidget::MyWidget(CustomStackedWidget *stackedWidget, QWidget *parent)
    2. : QWidget(parent)
    3. {
    4. ui.setupUi(this);
    5. }
    6.  
    7. MyWidget::MyWidget(int index, CustomStackedWidget *stackedWidget, QWidget *parent)
    8. : QWidget(parent)
    9. {
    10. ui.setupUi(this);
    11. this->stackedWidget = stackedWidget;
    12. this->index = index;
    13. ui.label->setText(QString::number(index,10));
    14. }
    15.  
    16. MyWidget::~MyWidget()
    17. {
    18.  
    19. }
    20.  
    21.  
    22. void MyWidget::on_pushButtonRemove_clicked() {
    23. this->stackedWidget->activatePreviousView();
    24. }
    25.  
    26. void MyWidget::on_pushButtonInsert_clicked() {
    27. MyWidget *newMyWidget = new MyWidget(this->index+1,this->stackedWidget);
    28. this->stackedWidget->activateNewWidget(newMyWidget);
    29. }
    30.  
    31. void MyWidget::on_pushButtonPop_clicked() {
    32. this->stackedWidget->popTo(0);
    33. }
    To copy to clipboard, switch view to plain text mode 


    You can see my test project in full here:
    http://www.easy-share.com/1909777246...WidgetTest.rar

    The problem that I'm having is that if I insert a lot of widgets into the stack and then pop back to the home screen and then do this like 5-10 times I got a memory warning (this have been tested on both Nokia N97 and Nokia 5800). This memory warning doesn't show on this small test project, as it is very light-weighted widgets that I use in the test. In the real application these widgets is more heavy. But I'm just curious if the solution I'm using seems right. If you wan't I could give you the full (giant) project but I really can't post it here.

    1. The widgets in the stacked widget should they all have the stacked widget as parent? It maybe doesn't matter as I always delete the widgets by my own when they are removed from the stacked widget?
    2. As you can see I'm using deleteLater to delete my widgets. It wouldn't really matter if I used delete instead as I always do deleteLater as the last thing and then the control returns to the event loop and the widget will be deleted?
    3. Is this a good approach at all? Should I think of another way instead of adding and deleting my widgets like this? The different steps that the user can take when using the application is quite complex so it seemed easy to just add and deleting like this without reuse the widgets. How would a solution where I reuse the widgets look like?

    I have been working with solving this for over a week and I would be very very glad for all help I can get. Thanks!

  13. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QStackedWidget and memory management

    Have you seen this article by Johan?

    http://doc.trolltech.com/qq/qq27-panelstack.html

    As a general remark, removing a widget from the stacked widget doesn't cause it to be deleted. You have to explicitely delete it yourself.

  14. #13
    Join Date
    Feb 2010
    Posts
    51
    Thanks
    9
    Thanked 14 Times in 4 Posts

    Default Re: QStackedWidget and memory management

    Thanks! I will take a look at the article.

    Yes, I know I need to delete them myself. I do:

    stackedWidget->removeWidget(widget);
    widget->deleteLater();

    Do you have any other comments of my code?

  15. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QStackedWidget and memory management

    If you are using a decent OS, it will not deallocate memory immediately because you might want it back a moment later so it's keeping it for you. When something else requests a large block of memory, the allocator will deallocate the chunk from your process. If you want to make sure the object is deleted, you can place some debug statement in its constructor or use tools such as valgrind to monitor the memory.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Memory Management Reg
    By BalaQT in forum Newbie
    Replies: 10
    Last Post: 4th February 2010, 12:43
  2. Recommend memory management literature
    By frenk_castle in forum General Programming
    Replies: 3
    Last Post: 18th October 2009, 20:30
  3. Memory management
    By cyberboy in forum Qt Programming
    Replies: 2
    Last Post: 12th June 2008, 20:48
  4. Memory management questions (im new to Qt)
    By scarvenger in forum Qt Programming
    Replies: 2
    Last Post: 6th May 2007, 07:41
  5. Memory management in QT
    By Gayathri in forum Qt Programming
    Replies: 1
    Last Post: 17th November 2006, 07:21

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.