首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >确定在Qt中按哪个快捷方式

确定在Qt中按哪个快捷方式
EN

Stack Overflow用户
提问于 2018-06-06 12:44:46
回答 2查看 881关注 0票数 3

我有一个QAction,我给它分配了多个快捷键

代码语言:javascript
复制
   test = new QAction();
   this->addAction(test);
   QList<QKeySequence> shortcuts;
   shortcuts << QKeySequence(Qt::Key_N) << QKeySequence(Qt::Key_T);
   test->setShortcuts(shortcuts);
   connect(test,SIGNAL(triggered()),this,SLOT(SomeFucntion()))

SomeFucntion中,我需要知道pressed....Is到底有哪条捷径?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-06 17:22:28

您可以在QSignalMapper中尝试一种更精细的模式,它可以避免需要定义尽可能多的快捷方式,但需要c++11 (至少这个实现)。

在窗口的构造函数中,使用以下代码声明QShortcut对象和QSignalMapper

代码语言:javascript
复制
QSignalMapper* signalMapper = new QSignalMapper(this);
QShortcut* sc1 = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_N), this);
QShortcut* sc2 = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_T), this);

connect(sc1, &QShortcut::activated, signalMapper, static_cast<void (QSignalMapper::*)(void)>(&QSignalMapper::map));
connect(sc2, &QShortcut::activated, signalMapper, static_cast<void (QSignalMapper::*)(void)>(&QSignalMapper::map));

signalMapper->setMapping(sc1, sc1);
signalMapper->setMapping(sc2, sc2);

QAction* action = new QAction();
connect(signalMapper, static_cast<void (QSignalMapper::*)(QObject*)>(&QSignalMapper::mapped),
    [action](QObject *object){

    QShortcut* sc = qobject_cast<QShortcut*>(object);
    if (sc)
    {
        action->setData(sc->key().toString());
        action->trigger();
    }
});

connect(action, &QAction::triggered, this, &MainWindow::doStuff);

由于QSignalMapper的工作方式,第三个连接是必需的:当一个快捷方式被激活时,由于第一和第二个连接,它将被通知给QSignalMapper,这将触发map()槽。

QSignalMapper::map()槽将扫描由setMapping() API创建的映射,该映射的第一个参数是映射对象,第二个参数将用于在识别发射对象后发出QSignalMapper的映射()槽。为此,它使用发送方()方法,并简单地将返回的指针与作为映射提供的映射QObject指针进行比较。

一旦QObject被识别,QSignalMapper将发出QSignalMapper::was (QObject*)信号,该信号的参数是给setMapping的第二个参数,在这种情况下,它与第一个相同,也就是指向被激活的QShortcut的指针。

我使用lambda来捕获这个信号,而在这个lambda中,我只需检查给定的参数是一个QShortcut指针,并在触发操作本身之前将其键序列存储在QAction的数据成员中。然后QAction::触发器()插槽将发出QAction::invoke ()信号,然后调用自定义插槽,在本例中是doStuff()。在那里,您可以检索密钥序列,并使用它做您想做的事情。

因此,时隙实现应该与此类似:

代码语言:javascript
复制
void MainWindow::doStuff()
{
    // use sender() to fetch data from action
    QAction* act = qobject_cast<QAction*>(sender());
    if (act)
    {
        QString sequence = act->data().toString();

        // debug output will show you the triggering key sequence
        qDebug() << sequence;

        // use sequence string to determine which shortcut was used

        // On Mike hint: better to reset data after use :)
        act.setData(QVariant());
    }
}

注意,我使用的是基于QObject指针的映射。通过这种方式,您可以重用signalMapper实例来连接来自其他类型的QObjects (例如QPushButtons)的事件,并在您的自定义槽中标识它们,还可以为QAction数据成员设置一个适当的值,该值可以存储通用的QVariant站点。

在使用QShortcut时,也要注意它们的康泰,也就是当它们处于活动状态时,就像在小部件或窗口作用域一样。

不幸的是,这种模式违背了纯oop原则,但可能比管理许多操作(图标、文本、工具提示等)更好。为了同样的目的。

编辑:回答评论

首先,让我澄清一下,您当然可以跳过QSignalMapper的使用。这只是一种可能的解决方案(不是更好,也许是过度杀戮.但在性能方面并不是很差)。

正如Mike在注释中所指出的,一种更简单的方法是对每个QShotcut::activated使用lambdas,但这将导致复制/粘贴代码,这是我一直试图避免的。相反,您可以在MainWindow中定义一个自定义插槽,并在触发它之前使用发送方()捕获QShortcut并准备操作。

无论如何,QSignalMapper IMHO更好地解释了您正在做的事情(从语义的角度来看),并且更灵活,以防您需要扩展到其他QObjects的连接,同时也支持其他类型的映射。

此外,这与我的个人品味有关,我喜欢将代码片段逻辑地压缩成小片段,而不是在几个插槽/函数中稀疏,因为它使我更容易阅读和在需要更改它时进行追溯,当然,只有这样做不会损害代码本身的质量。

票数 4
EN

Stack Overflow用户

发布于 2018-06-06 13:44:12

您应该为每个快捷方式创建一个单独的QAction,并使用一个QSignalMapper对它们进行分组。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50720742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档