Qt之 捕获键盘的组合键

一、简述

之前做了截图的小应用——Qt 之 简单截图功能,于是就想到了QQ截图直接使用组合键 Ctrl + Alt + A 就可以调用截图了。于是乎自己重写了 keyPressEvent事件用来捕获当前键盘的组合键,这里简单介绍一下Qt中如何捕获我们按下的某个按键或者组合键。

二、代码之路

其实代码很简单,比如我们也捕获当前键盘的 Ctrl + Alt + A组合键,以下代码就可以轻松实现。重写keyPressEvent事件来捕捉键盘消息,通过QKeyEvent ::key()方法和QKeyEvent::modifiers()方法获取需要捕捉的热键。

void MyWidget::keyPressEvent(QKeyEvent *event)
{
    // 捕捉 Ctrl + Alt + A 组合键;
    if (event->key() == Qt::Key_A  &&  event->modifiers() == (Qt::AltModifier | Qt::ControlModifier))
    {
        // 开始截图;
        startCatureImage();
    }

下面我们看一下QKeyEvent ::key()和QKeyEvent::modifiers()两个方法

QKeyEvent ::key()

Qt之 捕获键盘的组合键_第1张图片

从上面的注释中,我们需要知道返回的key值独立于当前的系统,并且不会区分大小写,但是我们可以通过QKeyEvent ::text()方法(见下图)或者到当前键值产生的Unicode文本,也就是我们想要判断当前按下的是大写的还是小写的可以通过此方法来判断。

Qt之 捕获键盘的组合键_第2张图片

比如我们按下大写的A,QKeyEvent ::text()返回值就是”A”,按下小写的a则返回”a”。所以这也是一种判断当前按下的字母是大写还是小写的一种方法。

但是QKeyEvent ::text()方法并不是所有的键都会有返回,比如字母abc、123、tab键、空格键、换行键这些是有具体的返回值,其他类似 Shift、 Control、Alt、Meta这些都是返回空字符串,具体大家可以自行测试。

// 测试代码(QKeyEvent ::text())
void MyWidget::keyPressEvent(QKeyEvent *event)
{
    qDebug() << event->text();
}

下面给出我测试的输出数据,大家可以看到我按下了一个大写的A,然后我按下了CAPS_LOOK键(切换大小写),我们发现这时QKeyEvent ::text()方法返回的值是空字符串,这一点Qt助手中也写的很清楚,或者通过按下Shift键加a键就是A,Shift键加A键就是a,这个大家应该都知道,顺便提一下。

Qt之 捕获键盘的组合键_第3张图片


这里QKeyEvent ::key()方法返回的key值我们可以搜索关键字Qt::Key,这里我们可以看到很多枚举值以及每个key值代表的具体含义。像Shift、 Control、Alt、Meta这些键都不不包括在这里面的,这些键具体我们可以看下面的modifiers()方法。

Qt之 捕获键盘的组合键_第4张图片


QKeyEvent ::modifiers()

Qt之 捕获键盘的组合键_第5张图片

我们看到modifiers() 会返回当前有没有按下 Ctrl 、 Alt 、Shift、Meta等这样的键。

我们看到注释中提到需要注意的地方,此方法返回的并不是一定就是正确的。注释中提到让我们同时按下两个Shift键,然后松开一个Shift键进行测试。

这里我发现了一个问题,也就是当我们按下一个Shift键之后,再按下另一个Shift键是不会触发keyPressEvent事件的,而如果我们换成Ctrl、或者Alt键时,我们按下一个Ctrl键(Alt键),触发了一个keyPressEvent事件,此时不松开这个键,再按下另一个Ctrl键(Alt键),这里会再次触发keyPressEvent事件,而如果是Shift键就不会再次触发keyPressEvent事件

这种情况需要大家注意一下。

我们可以看到QKeyEvent ::modifiers()方法的返回值为Qt::KeyboardModifiers,是一个QFlags类型,也就是说他可能包含多个Qt::KeyboardModifier值,也就是上文中我们看到可以使用如下语句来判断当前是否按下了Ctrl + Alt 键

if(event->modifiers() == (Qt::AltModifier | Qt::ControlModifier))

下图为Qt::KeyboardModifier的枚举值。具体包含哪些呢,这里我们熟悉的是Ctrl 、 Alt 、Shift这三个键,对应于Qt::ControlModifier、Qt::AltModifier、Qt::ShiftModifier,对于Qt::MetaModifier、Qt::KeypadModifier、Qt::GroupSwitchModifier,一般windows键盘不会有这三个键。而如果当前没有按下这些键,则返回Qt::NoModifier.

Qt之 捕获键盘的组合键_第6张图片

我们也可以使用QFlags::testFlag方法,比如用如下代码捕获Ctrl + Alt + A组合键,但是这种写法显然没有上面那种简洁。

if ((event->modifiers().testFlag(Qt::ControlModifier) && event->modifiers().testFlag(Qt::AltModifier)) && event->key() == Qt::Key_S)

遗留问题

其实这里还会有一些小问题,第一个就是登陆上了QQ之后,正常按下Ctrl + Alt + A组合键会自动调用QQ的截图功能,如果我们的Qt程序也想用这个组合键,这里是无法通过keyPressEvent事件捕捉的,因为当我们按下了Ctrl + Alt 键,这里keyPressEvent事件是能够捕捉到的,当再按下A键时不会触发keyPressEvent事件,而是直接调用了QQ的截图。

这里可能是热键冲突导致,因为QQ的截图快捷键Ctrl + Alt + A是全局的,无论当前我们是否打开QQ界面,或者聊天窗口,只要QQ没有退出且登录上,就可以使用Ctrl + Alt + A进行截图。而我们的Qt程序需要焦点在窗口上,才可以使用keyPressEvent事件捕捉键盘消息。

另外一点就是系统也会占用一些组合键,比如我之前用联想电脑使用Ctrl + Alt + S是无法捕捉到的,也就是我按下了Ctrl + Alt 键,再当我按下S键时,keyPressEvent事件没有响应,而我在惠普电脑上按下Ctrl + Alt + S键就弹出了系统信息的窗口(见下图),但是keyPressEvent事件仍然可以响应。

这一点需要大家注意一下。

Qt之 捕获键盘的组合键_第7张图片

对于以上遇到的两个问题后续需要查明一下具体的原因,如果有知道或者了解的小伙伴,欢迎一起交流。


其实写这篇文章的初衷并不是说如何用Qt捕获类似Ctrl + Alt + A这样的组合键,其实是因为在写这个的过程中遇到了一些值得思考的小问题,然后索性就将这些问题以博文的方式展现出来,顺便也介绍了一下Qt助手中QKeyEvent ::key()、QKeyEvent ::modifiers()两个方法。

其实在写文章之前,我对这两个方法也是简单带过,并没有仔细看文档的介绍,在写文章的过程中我再次看了文档的介绍,我了解到在捕获键盘消息时可能需要判断当前按下字母的大小写,可惜QKeyEvent ::key()方法并没有大小写的区分,但是提到了QKeyEvent ::text()方法,而这个方法也就是返回当前key的Unicode文本,而通过这个返回值,就可以正确地判断当前按键的大小写了,问题就是这么发现然后正确解决了。

所以,探索的过程还是很重要的,要一直保持一颗好奇心,善于发现问题,并解决问题

你可能感兴趣的:(Qt,qt,捕获按键,组合键,捕获组合键,捕获键盘)