I took your sample code and changed it to illustrate what I described in my latest comments:
Add a member variable to the MainWindow
declaration:
QMenu *menuStart;
The changed sample code:
// configure start menu:
menuStart = new QMenu(menuBtn);
menuStart->addAction(QString::fromUtf8("Product Details"),
[](bool){
qDebug() << "Product Details triggered"; }
);
menuStart->addAction(QString::fromUtf8("Memory Status"),
[](bool){
qDebug() << "Memory Status triggered"; }
);
//Menu Button
menuBtn->setIcon(QPixmap(":/new/prefix1/ic_menu_black.png"));
menuBtn->setMenu(menuStart);
statusBar()->addWidget(menuBtn);
connect(menuBtn,SIGNAL(clicked(bool)),this,SLOT(showPopupMenu()));
Note:
I set menuBtn
as parent of the menuStart
. Thus, menuBtn
should manage the destruction of menuStart
when it is destroyed itself.
The signal handler becomes shorter respectively:
void MainWindow::showPopupMenu()
{
menuStart->show(); // <-- trick to force layout of the menu before height() is called
// position menu relative to menuBtn at popup
menuStart->popup(
mapToGlobal(menuBtn->pos() - QPoint(0, menuStart->height())));
qDebug()<<"Menu Clicked!";
}
I did it carefully but couldn't test it (as it's no MCVE). So, please, take this with a "grain of salt".
Note:
I just realized that you use the "pre-Qt5" style of connecting signal handlers. Qt5 introduced a nice extension to its signals supporting function pointers as well as method pointers. Due to this, I was able to do the signal handlers simply as lambdas. (The lambdas are these [](bool){/*...*/}
I connected to the action slots. I was always suspicious about these new lambdas until I realized that they are an excellent tool to write very simple adapters for signal handlers as well as to make quite compact sample code.)
Update about Lambdas:
The brackets []
can be used to add variables to the environment (or context) of the lambda. If it is empty (as I used it) only global variables and functions can be used. Using [this]
means the current this
pointer is added to the environment. Thus, the lambda may access member variables of the current class instance.
When I recognized lambdas the first time, I saw often [=]
meaning the lambda gets the current context of the calling function (e.g. copies of every local function variable). I personally consider this as dangerous, especially for signal handlers. I will elaborate this a little bit:
The environment of a lambda allows to access "variables from outside" in the lambda body. Variables may be added by value or by reference. If a variable is provided by reference, it may be accessed in the lambda body but it will not grant that the life-time of the "outside" variable is long enough. (If it is not it results in a "dangling reference" with the same Undefined Behavior like a dangling pointer.) Does it help to prevent references at all? No. It is fine for primitive types (e.g. int
or float
) but could be inefficient (or even semantically wrong) for objects. Using pointer to objects instead, is as dangerous as using references. Thus, the enviroment of a lambda should be used with care.
As a rule of thumb, I personally use the following method to implement lambdas: I always start with an empty environment ([]
). If I recognize a variable which I need in the lambda I add it to the environment whereby I consider its sufficient lifetime (or look for an alternative).
Update:
As I'm a personal fan of SVG, I prepared a (similar) menu icon as SVG file:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="32" height="32">
<title>Start Menu</title>
<desc>Start Menu</desc>
<rect id="line"
x="4" y="6" width="24" height="4"
style="stroke:none;fill:#444"/>
<use xlink:href="#line" transform="translate(0,8)"/>
<use xlink:href="#line" transform="translate(0,16)"/>
</svg>
You may save this in a text file ic_menu_black.svg
and try to load it in your app.
Qt's importer has unfortunately only limited support of SVG. Thus, not every trick which is possible in SVG will work correctly in Qt. Therefore, I modified a copy of an icon out of our Qt application to be sure that this will work.