Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ownership of QAction in a QMenu

I was using Qt to build a basic GUI for an application and I have a few questions.. So I created the GUI, it works fine and I thought I would check something..

for(int i=0; i < 100000; i++)
{
    menu = new QMenu(this);
    act = new QAction("About", menu);
    menu->addAction(act);
    connect(act, SIGNAL(triggered()), this, SLOT(slotHelpAbout()));
    menuBar()->addMenu(menu)->setText("Help");
}
menuBar()->clear();

I use the QMenuBar of the QMainWindow class and fill it up with QMenu which are also filled up with QAction for wich I connect the triggered signal to a few slots.. This works fine but when I call clear it should delete the menu/action items contained by QMenuBar.. I am checking in task manager and the memory usage is still huge.. Even after:

    QList<QAction*> lst = menuBar()->actions();

    for(int i=0;i < lst.length(); i++)
    {
        delete lst.at(i);
    }

Shouldn't all memory used by the QMenus and QActions be freed ?

like image 357
elephantintheroom Avatar asked Jan 30 '12 20:01

elephantintheroom


2 Answers

No, they still exist in memory because they will only be deleted when menu is deleted, and menu is only deleted when this (assuming a QMainWindow) is deleted. Calling clear does not delete them.

The reason clear doesn't do this is because (among other things) it supports a scenario like the following: you have named variables referring to the QAction instances, and you want to rearrange them on your menu. You call clear to remove them all, then call addAction with those same actions in the order you desire.

If you want to delete them directly, you can just delete the menu bar. This will delete all the menus and actions parented to the menu bar recursively. Calling menuBar() automatically creates a new one if it does not exist, so you don't even have to worry about that.

#include <QtGui>

int main(int argc, char **argv) {
  QApplication app(argc, argv);

  QMainWindow m;

  QMenu *menu = m.menuBar()->addMenu("test");
  for (int i = 0; i < 30000; ++i) {
    menu->addAction(QString::number(i));  // memory going up, up, up...
  }

  delete m.menuBar();  // frees memory

  menu = m.menuBar()->addMenu("test2");  // Automatically creates new menu bar
  menu->addAction("test 2 action");

  m.show();

  return app.exec();
}
like image 152
Dave Mateer Avatar answered Nov 01 '22 02:11

Dave Mateer


QMenuBar::clear will do nothing for you since, as pointed out by @Dave Mateer, it only removes actions from the QMenuBar and doesn't delete them.

Also, deleting the list of actions from the QMenuBar will not cause each QMenu itself to be deleted.

Each QMenu that you have is parented to this which is presumably your QMainWindow. They will only be deleted when you delete the QMainWindow and not it's menu bar. You can change your code so that you parent each QMenu to the QMenuBar so that deleting the menu bar deletes the menus (and their actions). Alternatively you can keep hold of pointers to each individual menu and delete them manually.

like image 38
Troubadour Avatar answered Nov 01 '22 00:11

Troubadour