为什么这个QWidget eventFilter不会阻止其他小部件处理?

时间:2015-10-29 11:50:27

标签: qt

MyWidgetQDialog的子类,拥有QTextEdit * m_view成员。

我希望右键点击QTextEdit并显示与标准菜单不同的菜单。

目前,会显示MyWidget::context_menu创建的菜单,然后还会显示标准QTextEdit上下文菜单。

MyWidget :: MyWidget ()
{
    // ...
    m_view -> installEventFilter (this);
}

bool
MyWidget :: eventFilter (QObject * obj, QEvent * e)
{
    if (m_view == obj && QEvent :: MouseButtonPress == e -> type ())
    {
        auto me = dynamic_cast <QMouseEvent *> (e);

        if (Qt :: RightButton == me -> button ())
        {
            context_menu (m_view -> mapToGlobal (me -> pos ()));

            e -> accept ();

            return true;
        }
        else
            return QDialog :: eventFilter (obj, e);
    }
    else
        return QDialog :: eventFilter (obj, e);
}

更奇怪的是 - 如果我在我的自定义菜单外单击鼠标左键或右键单击以失去焦点,则标准上下文菜单会出现 - 只有在我选择其中一个时才显示我的菜单项目!

eventFilter都返回true并调用e->accept(),为什么标准菜单也会出现?

如果还有另一种正确的方法,那很好,但请解释为什么这两个小部件都会处理这个事件。

(顺便说一下,我也想知道为什么return trueQEvent::accept()都在设计中 - 它似乎多余但Qt设计非常智能,所以它是什么?原因是什么?)

1 个答案:

答案 0 :(得分:1)

显示自定义上下文菜单的正确方法是将context menu policy设置为Qt::CustomContextMenu。 然后使用QWidget::customContextMenuRequested(const QPoint & pos)信号显示您自己的菜单。

m_view->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));

顺便说一下,事件过滤器无法正常工作的原因是你要检查错误的对象。我不确定哪个对象负责在QEvent::ContextMenu事件期间触发QEvent::MouseButtonRelease事件。但即使您通过过滤鼠标按钮释放事件来使其工作,也是错误的。这不是显示上下文菜单的唯一情况。大多数键盘上还有一个菜单按钮,用于触发上下文菜单。但是,如果要过滤上下文菜单,则应检查事件是QEvent::ContextMenu并且对象是m_view->viewport()而不是m_view本身:

  if(e->type() == QEvent::ContextMenu && obj == m_view->viewport())