Sistema de eventos Qt: eventos de teclado

1. Introducción

La clase QKeyEvent se usa para describir un evento de teclado. Cuando se presiona o suelta una tecla del teclado, los eventos del teclado se envían al widget que tiene el foco de entrada del teclado.

La función key() de QKeyEvent puede obtener la clave específica Para todas las claves dadas en Qt, puede consultar la palabra clave Qt: :Key en la ayuda. Cabe señalar que la tecla Intro aquí es Qt::Key_Return; algunas teclas modificadoras del teclado, como Ctrl y Shift, etc., deben obtenerse mediante la función modificadores() de QKeyEvent, y puede usar Qt :: en la palabra clave KeyboardModifier de ayuda para ver todas las teclas modificadoras.

QKeyEvent tiene dos funciones de miembro de evento de teclado, que se declaran en el archivo de encabezado.h:

#include <QKeyEvent>

protected:
    void keyPressEvent(QKeyEvent *event); //键盘按下事件
    void keyReleaseEvent(QKeyEvent *event); //键盘松开事件

2. Operaciones comunes

Estas son algunas operaciones comunes:

// 键盘按下事件
void Widget::keyPressEvent(QKeyEvent * event)
{
    // 普通键
    switch (event->key())
    {
        // ESC键
        case Qt::Key_Escape:
            qDebug() <<"ESC";
        break;
        // 回车键
        case Qt::Key_Return:
            qDebug() <<"Enter";
        break;
        // F1键
        case Qt::Key_F1:
            qDebug() <<"F1";
        break;
    }

    // 两键组合
    if(event->modifiers() == Qt::ControlModifier) { // 如果按下了CTRL键
        if(event->key() == Qt::Key_M){
           qDebug()<<"CTRL + M";
        }
    }

    if(event->modifiers() == Qt::AltModifier) { // 如果按下了ALT键
       if(event->key() == Qt::Key_M)
           qDebug()<<"ALT + M";
    }

    if(event->modifiers() == Qt::ShiftModifier){ // 如果按下了Shift键
           if(event->key() == Qt::Key_M)
               qDebug()<<"Shift + M";
    }

    // 三键组合Shift + Ctrl + A的实现
    if (event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier) && event->key() == Qt::Key_A) {
        qDebug() << "CTRL + Shift + A";
    }
}

// 键盘释放事件
void Widget::keyReleaseEvent(QKeyEvent *event)
{
    // 方向UP键
    if(event->key() == Qt::Key_Up)
    {
        qDebug() << "release: "<< "up";
    }
}

Presione ESC, Enter, CTRL + M, ALT + M y otras teclas respectivamente, y el resultado de la ventana "Resultado de la aplicación" es el siguiente:

ESC
Enter
CTRL + M
ALT + M
release:  up

La siguiente figura enumera todas las teclas modificadoras:

 

3. Botón y repetición automática

La repetición automática significa que cuando se presiona y mantiene presionada una tecla del teclado (excepto la tecla modificadora), el evento de pulsación de tecla se enviará repetidamente. Qt está predeterminado para habilitar la repetición automática. Para implementar teclas de método abreviado como las teclas A+D, necesitas desactivar la repetición automática. La repetición automática se puede desactivar utilizando los siguientes métodos:

// 若自动重复则什么也不做
if(QKeyEvent::isAutoRepeat()) 
    return;

El rendimiento general de los eventos de teclado de Qt es que cuando se presiona una tecla:
1. KeyPressEvent() se activa por primera vez y isAutoRepeat() devuelve false

2. KeyReleaseEvent() no se activa, haga una pausa por un tiempo

3. Vuelva a activar keyPressEvent() y isAutoRepeat() devuelve verdadero

4. Activar keyReleaseEvent()

5. Si no se suelta el botón, isAutoRepeat() devuelve verdadero y vuelve al paso 3. Si se suelta el botón, isAutoRepeat() devuelve falso

Los beneficios de este artículo, gratis para recibir el paquete de materiales de aprendizaje de desarrollo Qt, video técnico, que incluye (base del lenguaje C ++, introducción a la programación Qt, mecanismo de señal y ranura QT, dibujo de imagen de desarrollo de interfaz QT, red QT, programación de base de datos QT, QT proyecto de combate, QSS, OpenCV, módulo rápido, preguntas de la entrevista, etc.) ↓↓↓↓↓↓Ver abajo↓↓Haga clic en la parte inferior del artículo para recibir la tarifa↓↓

4. Captura de teclado

Puede especificar solo un determinado control en la ventana para capturar eventos del teclado, de modo que otros controles no puedan obtener eventos del teclado, como se muestra a continuación.

MiBoton.h:

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>
#include <QPushButton>
#include <QKeyEvent>
#include <QDebug>

class MyButton : public QPushButton
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);

protected:
    void keyPressEvent(QKeyEvent *event);
};

#endif // MYBUTTON_H

MiBoton.cpp

#include "MyButton.h"

MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{

}

void MyButton::keyPressEvent(QKeyEvent *event)
{
    qDebug() << "button键盘按键事件:" << this->objectName();
    QWidget *ww = keyboardGrabber(); // 返回正在捕获键盘输入的部件,若没有则返回 0
    qDebug() << "正在捕获的控件:" << ww;

    if(event->key() == Qt::Key_Q) {
        qDebug() << "按下了Q键";
        this->releaseKeyboard();   // 释放捕获的键盘输入
     }
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QKeyEvent>
#include "MyButton.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);

protected:
    void keyPressEvent(QKeyEvent *event);

private:
    MyButton* m_pBtn1;
    MyButton* m_pBtn2;
};
#endif // WIDGET_H

Widget.cpp:

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(300,400);

    // 初始化按钮1
    m_pBtn1=new MyButton();
    m_pBtn1->setParent(this);
    m_pBtn1->setText("AAA");
    m_pBtn1->move(10,10);
    m_pBtn1->resize(100,100);
    m_pBtn1->setObjectName("aaa");
    // 初始化按钮2
    m_pBtn2=new MyButton();
    m_pBtn2->setParent(this);
    m_pBtn2->setText("BBB");
    m_pBtn2->move(150,10);
    m_pBtn2->resize(100,100);
    m_pBtn2->setObjectName("bbb");

    // 指定控件捕获键盘
    m_pBtn1->grabKeyboard();
    /*使按钮 AAA 捕获键盘,此时产生的键盘事件都只会发送给按钮 AAA,也就是说
        其他部件无法获得键盘事件。
        只有可见的部件才能捕获键盘输入,若 isVisible()返回 false,则该部件不能调用grabKeyboard()函数
    */
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event);

    qDebug()<<"Widget发生键盘事件";
}

Presione cualquier tecla y descubra que solo el botón AAA puede obtener eventos del teclado y el botón BBB no puede obtener eventos del teclado.

5. Haga clic en el botón del teclado, haga doble clic

En primer lugar, QTimer se usa para la implementación de botones de teclado con un solo clic y con doble clic. Cuando se trata de esto, la mayoría de las personas probablemente saben lo que está pasando, pero también hay un malentendido aquí, es decir, cómo distinguir entre botones simples -haga clic y haga doble clic. El intervalo de tiempo entre dos pulsaciones de teclas se utiliza aquí para distinguir . Es posible implementarlo en la pulsación o liberación. Aquí finalmente elijo implementarlo en la liberación, y hablaré sobre el motivo más adelante.

Varias variables relacionadas se definen en el archivo de encabezado:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QTimer>
#include <QDebug>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);

protected:
    void keyReleaseEvent(QKeyEvent *event);

private:
    QTimer* m_pTimer; // Ctrl双击定时器
    int m_nClickCnt = 0; // 点击次数
    bool m_bLongPress = false; // 是否为长按    
};
#endif // WIDGET_H

Mire el clic del botón del teclado, haga doble clic en la implementación:

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 定时器
    m_pTimer = new QTimer(this);
    connect(m_pTimer, &QTimer::timeout, [=]{
        m_nClickCnt = 0; // 计数清零
        m_pTimer->stop(); // 停止计时
        qDebug() << "键盘单击";
    });
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    Q_UNUSED(event);

    if(event->key() == Qt::Key_A) {
        // 计数期间,如果QTimer已开始,则不重新开始
        if(!m_pTimer->isActive())
            m_pTimer->start(500); // 500ms是判断双击的时间间隔,不唯一,可根据实际情况改变

        m_nClickCnt++; // 点击计数,在500ms内如果点击两次认为是双击
        if(m_nClickCnt >= 2) {
            m_nClickCnt = 0; // 计数清零
            m_pTimer->stop(); // 停止计时
            qDebug() << "键盘双击";
        }
    }
}

Haga clic y el número de clics dobles no se alcanza en 500 ms, es decir, timer_->stop() no se ejecuta; cuando se agota el tiempo, se activa la señal de tiempo de espera y se ejecuta la acción de clic. Permítanme mencionar aquí la función stop() Después de que QTimer ejecuta start(n), si no se detiene(), se ejecutará en un bucle.

6. Mantenga presionado el botón del teclado

Hasta ahora, se ha realizado la reutilización del clic del teclado y del doble clic, así que echemos un vistazo a cómo lidiar con la pulsación prolongada.

Para distinguir si se trata de una pulsación prolongada, QKeyEvent proporciona una función isAutoRepeat() para detectar automáticamente si la tecla se mantiene presionada.

  • Mantenga pulsado para volver verdadero
  • La pulsación no larga devuelve falso

Como se mencionó anteriormente, la distinción entre un solo clic y doble clic se puede usar en las funciones void keyPressEvent (QKeyEvent * evento) y void keyReleaseEvent (QKeyEvent * evento). De todos modos, hay una diferencia entre el tiempo de grabación y presionar-presionar o release-release ¿Por qué elegir implementarlo en la función de liberación del botón?

El problema es que la función de pulsación larga tiene que implementarse al mismo tiempo. Acabo de analizar que tanto si pulsas una pulsación larga como si no, la primera acción de pulsación es una pulsación no larga. Si está en void keyPressEvent(QKeyEvent *evento) Realizado, la pulsación prolongada inevitablemente agregará un clic adicional, que por supuesto no es lo que queremos;

Ahora que el análisis ha terminado, creo que es hora de que comencemos a escribir código.

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 定时器
    m_pTimer = new QTimer(this);
    connect(m_pTimer, &QTimer::timeout, [=]{
        m_nClickCnt = 0; // 计数清零
        m_pTimer->stop(); // 停止计时
        qDebug() << "键盘单击";
    });
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    Q_UNUSED(event);

    if(event->key() == Qt::Key_A) { // Qt::Key_Control经实测,长按永远不会使isAutoRepeat()为true
        // 是否是长按可以从release中直接判断
        if (!event->isAutoRepeat()) {
            // LongPress_初始值为false,如果非长按执行单击或双击动作判断
            // 如果长按会在长按里将其置true,在最后的Relese(非长按)里就不会执行单击、双击判断的动作
            if (!m_bLongPress) {
                if (!m_pTimer->isActive()) {
                    m_pTimer->start(500);
                }
                m_nClickCnt++;
                if (m_nClickCnt == 2){
                    m_nClickCnt = 0; // 计数清零
                    m_pTimer->stop(); // 停止计时
                    qDebug() << "键盘双击";
                }
            }
            m_bLongPress = false; // 置false
        }
        else{
            if (!m_bLongPress) {
                qDebug() << "键盘长按";
                // 限定长按只执行一次,最后会在Relese(非长按)里将LongPress_重新置false
                m_bLongPress = true;
            }
        }
    }
}

Los beneficios de este artículo, gratis para recibir el paquete de materiales de aprendizaje de desarrollo Qt, video técnico, que incluye (base del lenguaje C ++, introducción a la programación Qt, mecanismo de señal y ranura QT, dibujo de imagen de desarrollo de interfaz QT, red QT, programación de base de datos QT, QT proyecto de combate, QSS, OpenCV, módulo rápido, preguntas de la entrevista, etc.) ↓↓↓↓↓↓Ver abajo↓↓Haga clic en la parte inferior del artículo para recibir la tarifa↓↓ 

 

Supongo que te gusta

Origin blog.csdn.net/QtCompany/article/details/131743524
Recomendado
Clasificación