【问题标题】:How to make shortcuts trigger in a custom QMenu?如何在自定义 QMenu 中触发快捷方式?
【发布时间】:2019-12-03 01:07:24
【问题描述】:

我有一个上下文菜单 (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;
});

菜单是这样打开的(宿主类派生自QGraphicsView):

m_mainContextMenu.exec(mapToGlobal(m_clickedPos));

菜单显示操作 OK,但不是由 Ctrl+C 触发。我在主菜单中对操作使用了相同的方法,为什么会有所不同?

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

【问题讨论】:

  • 试试 m_copyNodeAction->setShortcutContext(Qt::ApplicationShortcut);
  • 没有帮助。我尝试了所有可能的上下文选项。

标签: qt qt5 qmenu qaction qkeysequence


【解决方案1】:

这是解决此问题的一种方法:

  1. 除了将动作添加到上下文菜单之外,还要将动作添加到父窗口小部件(动作应该是本地的,比如说一个列表视图):
m_listview->addAction(m_copyNodeAction);
  1. 将操作的shortcut context 设置为Qt::WidgetWithChildrenShortcut
m_copyNodeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
  1. 确保您创建的上下文菜单使用您的小部件作为其父级:
auto* m_mainContextMenu = new QMenu{tr("Main Context Menu"), m_listview};

有几点需要考虑:

  1. 默认情况下,这不会在触发操作时关闭上下文菜单,但自己实现起来相当简单

  2. 这使您可以在不显示上下文菜单的情况下触发操作(虽然您为什么要这样做?)

通过一些初步测试,这似乎也是 QtCreator 处理快捷方式的方式,并且似乎是处理此问题的正确 Qt 式方法,尽管这只是我的 2ct。

【讨论】:

    【解决方案2】:

    以下示例重现了您的错误。我还在 Qt 框架中进行了调试,并逐步检查了 QMenu::keyPressEventQAction::event,但似乎没有正确处理按下的键。

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

    #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();
    }
    

    【讨论】:

    • Cool :) 另一个问题是action-&gt;setShortcutVisibleInContextMenu(true); 已经添加到Qt 5.10 中,但我还必须使用旧版本。
    • @juzzlin:您的问题仍然没有解决。尝试从QAction 派生并覆盖eventkeyPressedEvent
    • 是的,我会尝试类似的方法。我还针对 Qt 提交了一个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 2019-06-07
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    相关资源
    最近更新 更多