Qt中使用eventFilter的鼠标右键单击选项

Mouse right click option using eventFilter in Qt

我有 QGraphicsView,它有很多 QGraphicsItem。我正在尝试在这些 QGraphicsItem 上创建右键单击菜单。右键单击菜单有多个选项。但只有第一个选项有效。这意味着,如果我点击第二个选项,它不起作用。如果我改变顺序(意味着第一个会到第二个位置,第二个会到第一个位置)那么第二个仍然不起作用。

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
               }
           }
       }
    }
 }    
  

始终仅适用于第一个鼠标右键单击选项。为什么会这样?

执行此类操作的通常方法是覆盖项目 class 的 QGraphicsItem::mouseReleaseEvent()QGraphicsItem::mousePressEvent() 功能。

这样,您无需执行任何操作(无需循环等...),它已由事件循环处理。

在这里你可以找到一个简单的例子:

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

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

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

来自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().

您只需要 QObject::connect() 您添加到上下文菜单的 QAction 到适当的位置(这里是“逻辑”),工作就完成了。


如果您更喜欢自己检查返回值,您只需一劳永逸地获取返回的 QAction*(只调用一次 QMenu::exec())并在其上进行分支。

例如:

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

        // 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
        }
        //...
    }
}

我个人更愿意坚持使用 signal-slot 连接而不是手动处理返回值,特别是因为每个 QAction 很可能已经连接到其相应的插槽。