Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically close QMenu

I have pretty specific situation. I want to place a QAction into QToolbar and reach following behaviour:

  1. Checkable QAction with icon.
  2. Classic arrow on the right side which is used for showing menu
  3. By pressing this arrow my QDialog should appears on screen instead of QMenu-like one

Now I'm a bit confused with implementing all this things together.

For now I've created QAction added it to toolbar and also created an empty QMenubecause I didn't get the idea of how to add the "dropdown" arrow another way.
So, I also connected my slot to QMenu aboutToShow() signal and now, I can create my dialog and exec() it just before QMenu shows. But here's the main problem appears: after I did everything with my dialog an click OK button QMenu trying to appear, but as it is empty it shows nothing and further actions become available only after I left-click somwhere to "close" this menu.

Is there any way to force QMenu not to show or can inherit from QMenu and reimplemnt its behaviour (I've tried to do such trick with exec() show() popup() methods of QMenu after subclassing from it, but none of them are being called when menu appears on the screen) ?

like image 515
tema Avatar asked Sep 01 '15 13:09

tema


1 Answers

Here's the solution, which worked for me.

class QCustomMenu : public QMenu
{
  Q_OBJECT
public:
  QCustomMenu(QObject *parent = 0):QMenu(parent){};
};

In code:

QAction* myActionWithMenu = new QAction ( "ActionText", toolbar);
QCustomMenu* myMenu = new QCustomMenu(toolbar);
connect(myMenu, SIGNAL(aboutToShow()), this, SLOT(execMyMenu()));

execMyMenu() implementation:

void execMyMenu(){
  m_activeMenu = (QCustomMenu*)sender(); // m_activeMenu -- private member of your head class, needs to point to active custom menu
  QMyDialog* dlg = new QMyDialog();
  // setup your dialog with needed information
  dlg->exec();
  // handle return information
  m_myTimer = startTimer(10); // m_myTimer -- private member of your head(MainWindow or smth like that) class
}

Now we have to handle timerEvent and close our menu:

void MyHeadClass::timerEvent(QTimerEvent *event)
{
    // Check if it is our "empty"-menu timer 
    if ( event->timerId()==m_myTimer )
    {
        m_activeMenu->close(); // closing empty menu
        killTimer(m_myTimer);  // deactivating timer
        m_myTimer = 0;         // seting timer identifier to zero
        m_activeMenu = NULL;   // as well as active menu pointer to NULL
    }
}

It works great on every platform and does what I wanted. Hope, this would help someone. I've spent week trying to find this solution.

like image 139
tema Avatar answered Sep 17 '22 23:09

tema