QT captures keyboard input and displays the input shortcut key combinations, and solves the problem that some key combinations (such as Ctrl+Shift+letters) cannot be recognized in the Linux environment

Recently I am working on a QT project, which requires identifying keyboard input keys to generate shortcut keys. There is a class QKeySequenceEdit in QT. Using this, you can directly obtain keyboard input. However, if you want to filter out the keys you do not want to recognize, you must rewrite it. ThekeyPressEvent(QKeyEvent *e) function.

At first I used this control to read shortcut keys, but due to other requirements I changed to using the QlineEdit control and rewritten its keyPressEvent(QKeyEvent * e) function, which simply implements reading keyboard input shortcut keys, is actually similar to QKeySequenceEdit. After all, the source code of the latter is encapsulated using the former. Due to project requirements, I used QlineEdit. Here’s how I got filtered keyboard input and the problems I encountered and how I solved it.

head File

#ifndef MYKEYKUAIJIE_H
#defineMYKEYKUAIJIE_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

The bool isValidKey(int key, Qt::KeyboardModifiers modifiers) function implements filtering keyboard input

Source File

#include "mykeykuaijie.h"

Mykeykuaijie::Mykeykuaijie(QWidget *parent)
    :QLineEdit(parent)
{
//installEventFilter(this)
CtrlShift = false;
}

void Mykeykuaijie::keyPressEvent(QKeyEvent *event)
{
    // Get the currently pressed key and modifier key
    int key = event->key();
    Qt::KeyboardModifiers modifiers = event->modifiers();
    QString KJtext;

    if (isValidKey(key, modifiers))
    {
        //If it is not a letter or F1-F12, it will not be set.
        if((key >= Qt::Key_A & amp; & amp; key <= Qt::Key_Z) || (key >= Qt::Key_F1 & amp; & amp; key <=
           Qt::Key_F12)){
            KJtext = QKeySequence(key | modifiers).toString();
            setText(KJtext);
            emit send_text(QKeySequence(key | modifiers).toString());
        }
    }
    // Not a valid key combination, reset the key sequence
    else
    {
        event->ignore();
        setText(KJtext);
    }
}

bool Mykeykuaijie::isValidKey(int key, Qt::KeyboardModifiers modifiers)
{
    // Only allow Alt, Ctrl, Shift and letter keys and F1 to F12 as key combinations
    return modifiers == Qt::ControlModifier ||
    modifiers == Qt::ShiftModifier ||
    modifiers == Qt::AltModifier ||
           (key >= Qt::Key_A & amp; & amp; key <= Qt::Key_Z) ||
           (key >= Qt::Key_F1 & amp; & amp; key <= Qt::Key_F12);
} 

I only recognize single letters, single F1-F12, Ctrl and the three modifier keys Alt and Shft combined with letters and F1-12

The above steps can basically identify the combination I want to identify under Windows.

but! ! !

My QT project is to be run in a Linux environment, so based on the above writing method, some key combinations cannot be recognized. These key combinations are:

1. Ctrl + F1-11

Reason: pressing Ctrl and then pressing F1-11 will recognize F1-11 as F25-35, which will naturally be filtered out by my filter function. Even if it is not filtered, the display will be incorrect.

solve:

 // If you press Ctrl + F1-F11
    if (event->modifiers() == Qt::ControlModifier & amp; & amp; event->key() >= Qt::Key_F25
         & amp; & amp; event->key() <= Qt::Key_F35)
    {
        // Recognize it as 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(& amp;newEvent);
    }

Just remove the identified F25-35 and re-add F1-11.

2. Shift + F1-12

Reference 1.

3. Ctrl + Shift + letter

This is a bit difficult, for the following reasons:

I added the printing information and found that when I pressed Ctrl + Shift on the keyboard, event->modifiers() included Qt::ControlModifier and Qt::ShiftModifier, but when I pressed the letter again, shift was blocked and event ->modifiers() only contains Qt::ControlModifier. I came up with a somewhat bizarre solution by referring to solutions on the Internet and thinking about it day and night.

Code first

 // Determine whether the Ctrl, Shift and Alt keys are pressed
    bool ctrlPressed = event->modifiers() & amp; Qt::ControlModifier;
    bool shiftPressed = event->modifiers() & amp; Qt::ShiftModifier;

//Solve that Ctrl + Shift + letters will block Shift and only display Ctrl + letters
if (ctrlPressed)
{
if(shiftPressed){
add(); //Determine whether the current shift key is pressed
}
add2(); //Because each time a key is pressed, the keyPressEvent function will be re-entered, so CtrlShift is used to determine whether shift was pressed before pressing the letter key.
if(event->key() >= Qt::Key_A & amp; & amp; event->key() <= Qt::Key_Z & amp; & amp; 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;
}
}

That is, after pressing Ctrl, first determine whether shift is still pressed, and then manually add Qt::ShiftModifier back to event->modifiers(). Since the keyPressEvent function is triggered every time a key is pressed, the add add2 functions I added are to prevent my bool from being reset when the letter key is pressed.

4. Alt + Shift + letter

Same as 3.

5. Ctrl + Alt + F1-12

This QT is really cruel. After pressing Ctrl + Alt and then pressing F1-12, nothing happens, so I can’t solve it hahaha

Finally, the writing above may be a bit messy. This is the detailed code of the source file for reference (creation is not easy, hahaha)

#include "mykeykuaijie.h"

Mykeykuaijie::Mykeykuaijie(QWidget *parent)
    :QLineEdit(parent)
{
//installEventFilter(this)
CtrlShift = false;
}

void Mykeykuaijie::keyPressEvent(QKeyEvent *event)
{
    // Get the currently pressed key and modifier key
    int key = event->key();
    Qt::KeyboardModifiers modifiers = event->modifiers();
    QString KJtext;

qDebug()<<modifiers<<"****"<<event;

    // Check if it is a valid key combination
        // If Shift + F1-F12 is pressed
    if (event->modifiers() == Qt::ShiftModifier & amp; & amp; event->key() >= Qt::Key_F13 & amp; & amp; event->key() <= Qt::Key_F24 )
    {
        // Recognize it as 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(& amp;newEvent);
    }
        // If you press Ctrl + F1-F11
    if (event->modifiers() == Qt::ControlModifier & amp; & amp; event->key() >= Qt::Key_F25 & amp; & amp; event->key() <= Qt::Key_F35 )
    {
        // Recognize it as 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(& amp;newEvent);
    }
/*
QKeyEvent newEvent(event->type(), event->key(), modifiers2,
event->text(), event->isAutoRepeat(), event->count());
Mykeykuaijie::keyPressEvent(& amp;newEvent);
*/
\t
        // Determine whether the Ctrl, Shift and Alt keys are pressed
    bool ctrlPressed = event->modifiers() & amp; Qt::ControlModifier;
    bool shiftPressed = event->modifiers() & amp; Qt::ShiftModifier;
bool altPressed = event->modifiers() & amp; Qt::AltModifier;

//Solve that Ctrl + Shift + letters will block Shift and only display Ctrl + letters
if (ctrlPressed)
{
if(shiftPressed){
add(); //Determine whether the current shift key is pressed
}
add2(); //Because each time a key is pressed, the keyPressEvent function will be re-entered, so CtrlShift is used to determine whether shift was pressed before pressing the letter key.
if(event->key() >= Qt::Key_A & amp; & amp; event->key() <= Qt::Key_Z & amp; & amp; CtrlShift2){
Qt::KeyboardModifiers modifiers2 = Qt::ShiftModifier | event->modifiers();
            QString KJtext2 = QKeySequence(key | modifiers2).toString();
qDebug()<<KJtext2;
            setText(KJtext2);
emit send_text(KJtext2);
}
}

//Solve the problem that Alt + Shift + letters will block Shift and only display Alt + letters
if(altPressed)
{
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A & amp; & amp; event->key() <= Qt::Key_Z & amp; & amp; 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))
    {
    //The situation of Ctrl + Shift + letters must be blocked here, otherwise Ctrl + Shift + letters will block Shift and only display Ctrl + letters.
    if (ctrlPressed){
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A & amp; & amp; event->key() <= Qt::Key_Z){
if(CtrlShift2){
return;
}
}
}
    //The situation of Alt + Shift + letters must be blocked here
    if (altPressed){
if(shiftPressed){
add();
}
add2();
if(event->key() >= Qt::Key_A & amp; & amp; event->key() <= Qt::Key_Z){
if(CtrlShift2){
return;
}
}
}
//Key, so that Ctrl + letter can be triggered normally
CtrlShift = false;
        //If it is not a letter or F1-F12, it will not be set.
        if((key >= Qt::Key_A & amp; & amp; key <= Qt::Key_Z) || (key >= Qt::Key_F1 & amp; & amp; key <= Qt::Key_F12)){
            KJtext = QKeySequence(key | modifiers).toString();
            setText(KJtext);
            emit send_text(QKeySequence(key | modifiers).toString());
        }
    }

    // Not a valid key combination, reset the key sequence
    else
    {
        event->ignore();
        setText(KJtext);
    }
\t
\t
}

bool Mykeykuaijie::isValidKey(int key, Qt::KeyboardModifiers modifiers)
{
    // Only allow Alt, Ctrl, Shift and letter keys and F1 to F12 as key combinations
    return modifiers == Qt::ControlModifier ||
    modifiers == Qt::ShiftModifier ||
    modifiers == Qt::AltModifier ||
           (key >= Qt::Key_A & amp; & amp; key <= Qt::Key_Z) ||
           (key >= Qt::Key_F1 & amp; & amp; key <= Qt::Key_F12);
}

void Mykeykuaijie::add(){
CtrlShift = true;
}
void Mykeykuaijie::add2(){
if(CtrlShift == true){
CtrlShift2 = true;
}else{
CtrlShift2 = false;
}
}


The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. CS entry skill treeLinux introductionFirst introduction to Linux37867 people are learning the system