Qt 如何在自定义QMenu中触发快捷方式?

Qt 如何在自定义QMenu中触发快捷方式?,qt,qt5,qmenu,qaction,qkeysequence,Qt,Qt5,Qmenu,Qaction,Qkeysequence,我有一个上下文菜单(QMenu),并向其中添加一个复制操作,如下所示: m_copyNodeAction = new QAction(tr("Copy node"), &m_mainContextMenu); m_copyNodeAction->setShortcut(QKeySequence("Ctrl+C")); m_copyNodeAction->setShortcutVisibleInContextMenu(true); m_mainContextMenu.addA

我有一个上下文菜单(QMenu),并向其中添加一个复制操作,如下所示:

m_copyNodeAction = new QAction(tr("Copy node"), &m_mainContextMenu);
m_copyNodeAction->setShortcut(QKeySequence("Ctrl+C"));
m_copyNodeAction->setShortcutVisibleInContextMenu(true);

m_mainContextMenu.addAction(m_copyNodeAction);

QObject::connect(m_copyNodeAction, &QAction::triggered, [this] () {
    std::cout << "Copy node triggered!" << std::endl;
});
菜单显示动作OK,但不会通过
Ctrl+C
触发。我在我的主菜单中使用了相同的操作方法,那么为什么会有所不同呢


我还尝试设置了一些其他快捷方式,但没有任何效果。

以下示例再现了您的错误。我还在Qt框架内部进行了调试,并逐步执行了
QMenu::keyPressEvent
QAction::event
,但似乎没有正确处理按下的键

QAction::event
中,事件类型
QEvent::Shortcut
从不出现。作为一种解决方法,我建议您从
QAction
派生并实现自己的
事件
函数

#include <QApplication>
#include <QFrame>
#include <QMenu>
#include <QAction>
#include <QDebug>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    QApplication::setAttribute(Qt::ApplicationAttribute::AA_DontShowShortcutsInContextMenus,false);
    auto widget = new QFrame;

    widget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
    int id=widget->grabShortcut(QKeySequence::Delete, Qt::ShortcutContext::WidgetShortcut);

    QObject::connect(widget, &QFrame::customContextMenuRequested, [widget,id](const QPoint& pos) {
        QMenu menu(widget);
        menu.setShortcutEnabled(id, true);
        auto action = new QAction("&Copy node", &menu);
        action->setShortcut(QKeySequence(QKeySequence::Delete));
        action->setShortcutVisibleInContextMenu(true);
        action->setShortcutContext(Qt::ShortcutContext::WidgetShortcut);

        QObject::connect(action, &QAction::triggered, []() {
            qDebug() << "Copy node triggered!";
        });

        menu.addAction(action);
        menu.exec(widget->mapToGlobal(pos));
        });

    widget->show();
    return a.exec();
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
QApplication::setAttribute(Qt::ApplicationAttribute::AA_DontShowShortcutsInContextMenus,false);
自动小部件=新QFrame;
widget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
int id=widget->grabShortcut(QKeySequence::Delete,Qt::ShortcutContext::WidgetShortcut);
QObject::connect(小部件,&QFrame::customContextMenuRequested,[widget,id](常量QPoint&pos){
QMenu菜单(小部件);
menu.setShortcutEnabled(id,true);
自动操作=新建QAction(“&复制节点,&菜单”);
操作->设置短切(QKeySequence(QKeySequence::Delete));
操作->设置ShortCutVisibleInTextMenu(真);
操作->设置ShortcutContext(Qt::ShortcutContext::WidgetShortcut);
QObject::connect(操作,&QAction::已触发,[](){
qDebug()映射全局(pos));
});
widget->show();
返回a.exec();
}

这里有一种方法:

  • 除了将动作添加到contextmenu之外,还将动作添加到父窗口小部件(动作应该是本地的,比如listview):
  • m_listview->addAction(m_copyNodeAction);
    
  • 将操作设置为
    Qt::WidgetWithChildrenShortcut
  • m_copyNodeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
    
  • 确保您创建的上下文菜单将您的小部件用作其父项:
  • auto*m_mainContextMenu=newqmenu{tr(“主上下文菜单”),m_listview};
    
    有几件事需要考虑:

  • 默认情况下,触发操作时不会关闭上下文菜单,但这对于您自己实现来说非常简单

  • 这允许您在不显示上下文菜单的情况下触发该操作(尽管您为什么要这样做,但环绕导航也很简单)


  • 通过一些前期测试,这似乎也是QtCreator处理快捷方式的方式,并且似乎是实现这一点的正确的Qt方式,尽管这只是我的2ct。

    尝试m_copyNodeAction->setShortcutContext(Qt::ApplicationShortcut);没有帮助。我尝试了所有可能的上下文选项。酷:)另一个问题是
    action->setShortCutVisibleContextMenu(true)
    已经添加到
    Qt5.10
    中,但我必须使用一个旧版本。@juzzlin:你的问题仍然没有解决。试着从
    QAction
    派生并覆盖
    event
    keyPressedEvent
    。是的,我会尝试类似的方法。我还对Qt提出了一个bug。
    #include <QApplication>
    #include <QFrame>
    #include <QMenu>
    #include <QAction>
    #include <QDebug>
    
    int main(int argc, char* argv[])
    {
        QApplication a(argc, argv);
        QApplication::setAttribute(Qt::ApplicationAttribute::AA_DontShowShortcutsInContextMenus,false);
        auto widget = new QFrame;
    
        widget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
        int id=widget->grabShortcut(QKeySequence::Delete, Qt::ShortcutContext::WidgetShortcut);
    
        QObject::connect(widget, &QFrame::customContextMenuRequested, [widget,id](const QPoint& pos) {
            QMenu menu(widget);
            menu.setShortcutEnabled(id, true);
            auto action = new QAction("&Copy node", &menu);
            action->setShortcut(QKeySequence(QKeySequence::Delete));
            action->setShortcutVisibleInContextMenu(true);
            action->setShortcutContext(Qt::ShortcutContext::WidgetShortcut);
    
            QObject::connect(action, &QAction::triggered, []() {
                qDebug() << "Copy node triggered!";
            });
    
            menu.addAction(action);
            menu.exec(widget->mapToGlobal(pos));
            });
    
        widget->show();
        return a.exec();
    }