最近在做一个QT项目,需要识别键盘输入的按键来生成快捷键,在QT中有一个类QKeySequenceEdit,使用这个可以直接获取键盘输入,不过想要实现过滤掉不想要识别的按键得要重写它的keyPressEvent(QKeyEvent *e)函数。
刚开始我是使用这个控件来实现读取快捷键的,但是由于别的要求我改成了用QlineEdit控件,重写 它的keyPressEvent(QKeyEvent *e)函数,单是实现读取键盘输入快捷键这个和QKeySequenceEdit其实也差不多,毕竟后者的源码就是使用前者来进行封装的。由于项目需求所以我就用了QlineEdit。下面是我获取过滤键盘输入的方法以及遇到的问题和解决方法。
头文件
#ifndef MYKEYKUAIJIE_H
#define MYKEYKUAIJIE_H
#include <QKeySequenceEdit>
#include <QLineEdit>
#include <QKeyEvent>
#include <QDebug>
#include <QTimer>
class Mykeykuaijie : public QLineEdit
{
Q_OBJECT
public:
explicit Mykeykuaijie(QWidget *parent = nullptr);
signals:
void send_text(QString text);
private:
void keyPressEvent(QKeyEvent *event) override;
bool isValidKey(int key, Qt::KeyboardModifiers modifiers);
};
#endif // MYKEYKUAIJIE_H
bool isValidKey(int key, Qt::KeyboardModifiers modifiers)函数实现过滤键盘输入
源文件
#include "mykeykuaijie.h"
Mykeykuaijie::Mykeykuaijie(QWidget *parent)
:QLineEdit(parent)
{
//installEventFilter(this)
CtrlShift = false;
}
void Mykeykuaijie::keyPressEvent(QKeyEvent *event)
{
// 获取当前按下的键和修饰键
int key = event->key();
Qt::KeyboardModifiers modifiers = event->modifiers();
QString KJtext;
if (isValidKey(key, modifiers))
{
//不是字母或者F1-F12就不设置
if((key >= Qt::Key_A && key <= Qt::Key_Z) || (key >= Qt::Key_F1 && key <=
Qt::Key_F12)){
KJtext = QKeySequence(key | modifiers).toString();
setText(KJtext);
emit send_text(QKeySequence(key | modifiers).toString());
}
}
// 不是有效的组合键,重置键序列
else
{
event->ignore();
setText(KJtext);
}
}
bool Mykeykuaijie::isValidKey(int key, Qt::KeyboardModifiers modifiers)
{
// 只允许 Alt、Ctrl、Shift和字母键以及 F1 到 F12 作为组合键
return modifiers == Qt::ControlModifier ||
modifiers == Qt::ShiftModifier ||
modifiers == Qt::AltModifier ||
(key >= Qt::Key_A && key <= Qt::Key_Z) ||
(key >= Qt::Key_F1 && key <= Qt::Key_F12);
}
我只识别单个字母、单个F1-F12、Ctrl和Alt和Shft三个修饰键与字母和F1-12的组合
以上这些步骤在windows下是基本都能够识别出我想识别出的组合。
但是!!!
我的QT项目是要在linux环境下运行的,所以单单以上面的写法,部分按键组合出现了不能识别的问题,这些按键组合有:
1、Ctrl+F1-11
原因:Ctrl按下后再按F1-11会将F1-11识别成F25-35,自然会被我的过滤函数过滤掉,就算不过滤也会显示不正确
解决:
// 如果按下的是Ctrl + F1-F11
if (event->modifiers() == Qt::ControlModifier && event->key() >= Qt::Key_F25
&& event->key() <= Qt::Key_F35)
{
// 将其识别为F1-F12
int fKey = event->key() - Qt::Key_F25 + Qt::Key_F1;
QKeyEvent newEvent(event->type(), fKey, event->modifiers(), event->text(),
event->isAutoRepeat(), event->count());
Mykeykuaijie::keyPressEvent(&newEvent);
}
就是将识别成的F25-35去掉重新加上F1-11。
2、Shift+F1-12
参考1、
3、Ctrl+Shift+字母
这个就有点难度了,原因:
我加入了打印信息发现,我键盘按下Ctrl+Shift时,event->modifiers()是包含Qt::ControlModifier和Qt::ShiftModifier的,但是我再按下字母时,shift就被屏蔽了,event->modifiers()是只包含Qt::ControlModifier了。我通过参考网上的解法以及日思夜想,有了一个有点奇葩的解法
先上代码
// 判断是否按下了 Ctrl 和 Shift 和 Alt键
bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
//解决Ctrl+Shift+字母会屏蔽Shift只显示Ctrl+字母
if (ctrlPressed)
{
if(shiftPressed){
add(); //判断当前shift键是否按下
}
add2(); //因为每次按下一个按键都会重新进入keyPressEvent函数,所以根据CtrlShift来判断按下字母按键前是否按了shift
if(event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z && CtrlShift2){
Qt::KeyboardModifiers modifiers2 = Qt::ShiftModifier | event->modifiers();
QString KJtext2 = QKeySequence(key | modifiers2).toString();
qDebug()<<KJtext2;
setText(KJtext2);
emit send_text(KJtext2);
}
}
void Mykeykuaijie::add(){
CtrlShift = true;
}
void Mykeykuaijie::add2(){
if(CtrlShift == true){
CtrlShift2 = true;
}else{
CtrlShift2 = false;
}
}
就是按下Ctrl后,先判断是否还按下了shift,然后手动帮event->modifiers()加回Qt::ShiftModifier。由于每次按下一次按键都会触发keyPressEvent函数,所以我加的add add2这些函数就是为了防止按下字母键时重置我的判断shift是否按下的bool。
4、Alt+Shift+字母
同3、
5、Ctrl+Alt+F1-12
这个QT是真的狠,按下Ctrl+Alt后再按F1-12后无任何反应,所以我 哈哈哈解决不了
最后,上面写得可能有点乱,这是源文件详细代码,可以参考(创作不易,那个哈哈哈)
#include "mykeykuaijie.h"
Mykeykuaijie::Mykeykuaijie(QWidget *parent)
:QLineEdit(parent)
{
//installEventFilter(this)
CtrlShift = false;
}
void Mykeykuaijie::keyPressEvent(QKeyEvent *event)
{
// 获取当前按下的键和修饰键
int key = event->key();
Qt::KeyboardModifiers modifiers = event->modifiers();
QString KJtext;
qDebug()<<modifiers<<"****"<<event;
// 检查是否是有效的组合键
// 如果按下的是Shift + F1-F12
if (event->modifiers() == Qt::ShiftModifier && event->key() >= Qt::Key_F13 && event->key() <= Qt::Key_F24)
{
// 将其识别为F1-F12
int fKey = event->key() - Qt::Key_F13 + Qt::Key_F1;
QKeyEvent newEvent(event->type(), fKey, event->modifiers(), event->text(), event->isAutoRepeat(), event->count());
Mykeykuaijie::keyPressEvent(&newEvent);
}
// 如果按下的是Ctrl + F1-F11
if (event->modifiers() == Qt::ControlModifier && event->key() >= Qt::Key_F25 && event->key() <= Qt::Key_F35)
{
// 将其识别为F1-F12
int fKey = event->key() - Qt::Key_F25 + Qt::Key_F1;
QKeyEvent newEvent(event->type(), fKey, event->modifiers(), event->text(), event->isAutoRepeat(), event->count());
Mykeykuaijie::keyPressEvent(&newEvent);
}
/*
QKeyEvent newEvent(event->type(), event->key(), modifiers2,
event->text(), event->isAutoRepeat(), event->count());
Mykeykuaijie::keyPressEvent(&newEvent);
*/
// 判断是否按下了 Ctrl 和 Shift 和 Alt键
bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
bool altPressed = event->modifiers() & Qt::AltModifier;
//解决Ctrl+Shift+字母会屏蔽Shift只显示Ctrl+字母
if (ctrlPressed)
{
if(shiftPressed){
add(); //判断当前shift键是否按下
}
add2(); //因为每次按下一个按键都会重新进入keyPressEvent函数,所以根据CtrlShift来判断按下字母按键前是否按了shift
if(event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z && CtrlShift2){
Qt::KeyboardModifiers modifiers2 = Qt::ShiftModifier | event->modifiers();
QString KJtext2 = QKeySequence(key | modifiers2).toString();
qDebug()<<KJtext2;
setText(KJtext2);
emit send_text(KJtext2);
}
}
//解决Alt+Shift+字母会屏蔽Shift只显示Alt+字母
if (altPressed)
{
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z && CtrlShift2){
Qt::KeyboardModifiers modifiers2 = event->modifiers() | Qt::ShiftModifier;
QString KJtext2 = QKeySequence(key | modifiers2).toString();
qDebug()<<KJtext2;
setText(KJtext2);
emit send_text(KJtext2);
}
}
if (isValidKey(key, modifiers))
{
//这里得屏蔽掉Ctrl+Shift+字母的情况,否则Ctrl+Shift+字母会屏蔽Shift只显示Ctrl+字母
if (ctrlPressed){
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z){
if(CtrlShift2){
return;
}
}
}
//这里得屏蔽掉Alt+Shift+字母的情况
if (altPressed){
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z){
if(CtrlShift2){
return;
}
}
}
//关键,使得可以正常触发Ctrl+字母
CtrlShift = false;
//不是字母或者F1-F12就不设置
if((key >= Qt::Key_A && key <= Qt::Key_Z) || (key >= Qt::Key_F1 && key <= Qt::Key_F12)){
KJtext = QKeySequence(key | modifiers).toString();
setText(KJtext);
emit send_text(QKeySequence(key | modifiers).toString());
}
}
// 不是有效的组合键,重置键序列
else
{
event->ignore();
setText(KJtext);
}
}
bool Mykeykuaijie::isValidKey(int key, Qt::KeyboardModifiers modifiers)
{
// 只允许 Alt、Ctrl、Shift和字母键以及 F1 到 F12 作为组合键
return modifiers == Qt::ControlModifier ||
modifiers == Qt::ShiftModifier ||
modifiers == Qt::AltModifier ||
(key >= Qt::Key_A && key <= Qt::Key_Z) ||
(key >= Qt::Key_F1 && key <= Qt::Key_F12);
}
void Mykeykuaijie::add(){
CtrlShift = true;
}
void Mykeykuaijie::add2(){
if(CtrlShift == true){
CtrlShift2 = true;
}else{
CtrlShift2 = false;
}
}