Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
672 views
in Technique[技术] by (71.8m points)

c++ - how to create menu in statusbar in qt like PC start menu

In my qt application, i have designed status bar with few icons. On the left of my status bar i have added menu icon (QPixmap) when i click that icon i need to show a menu similar to PC start menu. I searched a lot but i did not found Qwidget for this.

This is my qt application window

As per my recent comment i added my edited code below since i cannot add the code in comment section, plz suggest a solution

//Menu Button
    menuBtn->setIcon(QPixmap(":/new/prefix1/ic_menu_black.png"));
    statusBar()->addWidget(menuBtn);
    connect(menuBtn,SIGNAL(clicked(bool)),this,SLOT(showPopupMenu()));

void MainWindow::showPopupMenu(){


    QMenu qMenuStart;

    QAction qCmdStart1(QString::fromUtf8("Product Details"), &qMenuStart);
    qMenuStart.addAction(&qCmdStart1);

    QAction qCmdStart2(QString::fromUtf8("Memory Status"), &qMenuStart);
    qMenuStart.addAction(&qCmdStart2);

    QObject::connect(&qCmdStart1, &QAction::triggered,[](bool){
        qDebug() << "Product Details triggered"; }
    );
    QObject::connect(&qCmdStart2, &QAction::triggered,[](bool){
        qDebug() << "Memory Status triggered"; }
    );

    qMenuStart.exec();

    menuBtn->setMenu(&qMenuStart);

    qMenuStart.show();
    qMenuStart.popup(mapToGlobal(pos() - QPoint(0, qMenuStart.height())));

    qDebug()<<"Menu Clicked!";

}

popup menu on click of menu button

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...