QT捕获键盘输入,并将输入快捷键组合显示出来,并解决在linux环境下部分按键组合(如Ctrl+Shift+字母)不能识别问题

最近在做一个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;
	}
}


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值