Home > Net >  Mouse right click option using eventFilter in Qt
Mouse right click option using eventFilter in Qt

Time:04-06

I have QGraphicsView, which has many QGraphicsItem. I am trying to create a right click menu on these QGraphicsItem. Right click menu has multiple options. But only 1st option works. It means, if I click on 2nd option, it does not work. If I change the sequence ( means 1st one will go to 2nd position, and 2nd one will come to 1st position ) then still 2nd one will not work.

bool myClass::eventFilter(QObject *watched, QEvent *event)
{
  switch(event->type())
  {
    case QEvent::ContextMenu:
    {
        foreach(QGraphicsItem* pItem, _scene->items())
        {
            if(pItem->isUnderMouse())
            {     
               QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
               menu = new QMenu(this);    
               myMenu = menu->addMenu("Copy");
               myMenu ->addAction(Name);
               myMenu ->addAction(Address);
               if(Name == menu->exec(mouseEvent->globalPos()))
               {
                   // logic
               }
               if(Address == menu->exec(mouseEvent->globalPos()))
               {
                   // logic
               }
           }
       }
    }
 }    
  

Always works only 1st mouse right click option. Why is so ?

CodePudding user response:

The usual way to do something like this is to override the QGraphicsItem::mouseReleaseEvent() or QGraphicsItem::mousePressEvent() function of your item class.

This way, you won't have to do anything (no looping, etc...), it is already handled by the event loop.

Here you can find a simple example:

void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    if(event->button() == Qt::RightButton)
    {
        QMenu my_menu(this);

        // Build your QMenu the way you want
        my_menu->addAction(my_first_action);
        my_menu->addAction(my_second_action);
        //...

        my_menu->exec(event->globalPos());
    }
}

From the Qt documentation:

Note that all signals are emitted as usual. If you connect a QAction to a slot and call the menu's exec(), you get the result both via the signal-slot connection and in the return value of exec().

You just need to QObject::connect() the QActions you added to the context menu to the proper slots (here goes the "logic") and the job is done.


If you prefer to check the returned value by yourself, you just have to get the returned QAction* once and for all (only one call to QMenu::exec()) and branch on it.

For example:

void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    if(event->button() == Qt::RightButton)
    {
        QMenu my_menu(this);

        // Build your QMenu the way you want
        my_menu->addAction(my_first_action);
        my_menu->addAction(my_second_action);
        //...

        QAction * triggered = my_menu->exec(event->globalPos());
        if(triggered == my_first_action)
        {
            // Do something
        }
        else if(triggered == my_second_action)
        {
            // Do some other thing
        }
        //...
    }
}

I would personnally prefer to stick with the signal-slot connections instead that manually handling the returned value, especially since each QAction is most likely to be already connected to its corresponding slot.

  • Related