Qt イベント システム: キーボード イベント

1. はじめに

QKeyEvent クラスは、キーボード イベントを記述するために使用されます。キーボードのキーが押されるか放されると、キーボード イベントがキーボード入力フォーカスを持つウィジェットに送信されます。

QKeyEvent の key() 関数は特定のキーを取得できます。Qt で指定されたすべてのキーについては、ヘルプで Qt: :Key キーワードを確認できます。ここでの Enter キーは Qt::Key_Return であることに注意してください。Ctrl や Shift などのキーボード上の一部の修飾キーは、QKeyEvent の modifiers() 関数を使用して取得する必要があり、Qt を使用できます。 :: help KeyboardModifier キーワードですべての修飾キーを表示します。

QKeyEvent には 2 つのキーボード イベント メンバー関数があり、ヘッダー ファイル .h で宣言されています。

#include <QKeyEvent>

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

2. 共通操作

一般的な操作をいくつか示します。

// 键盘按下事件
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";
    }
}

ESC、Enter、CTRL + M、ALT + M、その他のキーをそれぞれ押すと、「アプリケーション出力」ウィンドウの出力は次のようになります。

ESC
Enter
CTRL + M
ALT + M
release:  up

次の図は、すべての修飾キーをリストしています。

 

3. ボタンとオートリピート

自動リピートとは、キーボード上のキー (修飾キーを除く) が押し続けられると、キー押下イベントが繰り返し送信されることを意味します。Qt のデフォルトでは自動リピートが有効になっています。キー A+D などのショートカット キーを実装するには、自動リピートをオフにする必要があります。自動リピートは、次の方法を使用してオフにできます。

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

Qt のキーボード イベントの全体的なパフォーマンスは、キーが押されたとき:
1. KeyPressEvent() が初めてトリガーされ、isAutoRepeat() が false を返す

2. KeyReleaseEvent() がトリガーされないため、しばらく停止します。

3. keyPressEvent() を再度トリガーすると、isAutoRepeat() が true を返します。

4. keyReleaseEvent()をトリガーする

5. ボタンが離されていない場合、isAutoRepeat() は true を返し、ステップ 3 に戻ります。ボタンが離されている場合、isAutoRepeat() は false を返します。

この記事の利点は、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、Qt プログラミング入門、QT シグナルおよびスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT データベース プログラミング、QTプロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビューの質問など) ↓↓↓↓下記を参照↓↓記事下部をクリックして料金を受け取ります↓↓

4. キーボードキャプチャ

以下に示すように、ウィンドウ内の特定のコントロールのみを指定してキーボード イベントをキャプチャし、他のコントロールがキーボード イベントを取得できないようにすることができます。

MyButton.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

MyButton.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();   // 释放捕获的键盘输入
     }
}

ウィジェット.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

ウィジェット.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发生键盘事件";
}

任意のキーを押すと、ボタン AAA のみがキーボード イベントを取得でき、ボタン BBB はキーボード イベントを取得できないことがわかります。

5. キーボードボタンのクリック、ダブルクリック

まず、QTimer はキーボード ボタンのシングルクリックとダブルクリックの実装に使用されます。これについては、おそらくほとんどの人が何が起こっているかを知っているでしょうが、ここでも誤解があります。 -クリックしてダブルクリックします。ここでは2 つのキーを押す間隔を区別するために使用されています。プレスまたはリリースで実装することが可能です。ここでは最終的にリリースで実装することにしました。理由は後ほど説明します。

いくつかの関連変数がヘッダー ファイルで定義されています。

#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

キーボード ボタンのクリック、ダブルクリックの実装を見てください。

#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() << "键盘双击";
        }
    }
}

をクリックすると、500 ミリ秒以内にダブルクリックの回数に達しません。つまり、timer_->stop() は実行されません。時間がなくなると、タイムアウト信号がトリガーされ、クリック アクションが実行されます。ここで stop() 関数について説明しますが、QTimer は start(n) を実行した後、stop() を実行しない場合はループで実行されます。

6.キーボードボタンを長押しします。

ここまではキーボードのクリックとダブルクリックの再利用が実現できたので、長押し時の対処法を見てみましょう。

長押しかどうかを区別するために、QKeyEvent はキーが長押しされたかどうかを自動的に検出する isAutoRepeat() 関数を提供します。

  • 長押しすると true が返されます
  • 長押し以外の場合は false を返します

前述したように、シングルクリックとダブルクリックの区別は、 void keyPressEvent(QKeyEvent *event) 関数と void keyReleaseEvent(QKeyEvent *event) 関数で使用できますが、とにかく、記録時間とプレスプレスまたはプレスには違いがあります。 release-release. ボタンリリース機能にこれを実装することを選択した理由は何ですか?

問題は、長押し機能も同時に実装しなければならないことですが、長押ししても長押ししなくても、最初の押下動作は非長押しであると分析したところ、 void keyPressEvent(QKeyEvent) *event) 長押しすると必然的に追加のクリックが追加されることがわかりましたが、これはもちろん望んでいることではありません。

分析が終わったので、コードを書き始めるときが来たと思います。

#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;
            }
        }
    }
}

この記事の利点は、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、Qt プログラミング入門、QT シグナルおよびスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT データベース プログラミング、QTプロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビューの質問など) ↓↓↓↓下記を参照↓↓記事下部をクリックして料金を受け取ります↓↓ 

 

おすすめ

転載: blog.csdn.net/QtCompany/article/details/131743524