MyWidget
是QDialog
的子类,拥有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 true
和QEvent::accept()
都在设计中 - 它似乎多余但Qt设计非常智能,所以它是什么?原因是什么?)
答案 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())