1

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

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

m_mainContextMenu.exec(mapToGlobal(m_clickedPos));

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

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

4

2 回答 2

1

以下示例重现了您的错误。我还在 Qt 框架中进行了调试,并逐步完成了QMenu::keyPressEventand QAction::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();
}
于 2019-07-25T07:29:38.137 回答
1

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

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

有几点需要考虑:

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

  2. 这使您可以在不显示上下文菜单的情况下触发操作(尽管您为什么要这样做,但环游也很简单?)

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

于 2020-01-16T01:32:41.357 回答