将事件添加到 QPlainTextEdit 中的上下文菜单

Adding event to the context menu in QPlainTextEdit

这是我右键单击 QPlainTextEdit 后的上下文菜单。我想添加功能以从 上下文菜单 中的文件加载数据。我可以吗?怎么样?

方法一:QPlainTextEdit::contextMenuEvent

您应该覆盖 Qt 文档中提到的 QPlainTextEdit::contextMenuEvent

void MyQPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu *menu = createStandardContextMenu();
    menu->addAction(tr("My Menu Item"));
    //...
    menu->exec(event->globalPos());
    delete menu;
}

您可以连接 QAction::triggered signal to your method (slot) to load the data or you can use one of the QMenu::addAction 重载,这样您就可以直接指定插槽。

如果不想subclassQPlainTextEdit(覆盖contextMenuEvent),可以在Qt中使用event filtering

注意 contextMenuEvent() 仅在 contextMenuPolicy is not set (or set to its default value Qt::DefaultContextMenu)

时调用

方法二:QWidget::customContextMenuRequested

作为替代方案,您可以使用 Qt 的信号和槽机制在用户请求时创建上下文菜单。

contextMenuPolicy属性应该设置为Qt::CustomContextMenu,在这种情况下QWidget::customContextMenuRequested 信号在用户请求上下文菜单时调用。这个信号应该连接到你自己的插槽,它应该创建上下文菜单,如上面的代码(方法 1)所示。

在 Qt 设计器中使用 MyQPlainTextEdit

要在 .ui 文件中使用您的 MyQPlainTextEdit,您应该将其实现为升级的 QPlainTextEdit 并在您的 .ui 文件中使用它而不是常规 QPlainTextEdit。有关详细信息,请参阅 Qt documentation

为了能够在 Qt Designer 中使用您的 class,您不应忘记像 the AnalogClock example. Note that implementing such a constructor is always a good idea, because Qt typically manages ownership through a child-parent relationship.[=42 中那样实现接受父 QWidget 的构造函数=]

基于@m7913d 的回答。

这些技术的缺点是您必须从 QPlainTextEdit class 派生一个非常小的扩展。我的首选方法,尤其是在使用基于设计器的小部件时,是添加一个事件过滤器,并过滤掉鼠标按钮按下的鼠标事件

MyWidget::MyWidget(...)
{
    ...
    ui->plainTextEdit->installEventFiler( this )
}

MyWidget::eventFilter( QObject * obj, QEvent * event )
{
    if ( ( obj == ui->plainTextEdit ) 
      && ( event->type() = QEvent::MouseButtonPress ) 
      && ( dynamic_cast< QMouseEvent * >( event )->buttons() & Qt::MouseButton::RightButton )
    {
        // create menu
        auto menu = ui->plainTextEdit->createStandardContextMenu();
        // modify menu
        menu->exec( mouseEvent->globalPos() );
        delete menu;
        return true;
    }
    return false;
}