【QT学习】QKeyEvent键盘事件制作简单软件盘

文章目录

QKeyEvent键盘事件

  • 构造函数:
    • QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text = QString(), bool autorep = false, ushort count = 1)
    • 参数说明:
      • type --> 事件的类型(QEvent::KeyPress、QEvent::KeyRelease、QEvent::ShortCutOverride)
      • key --> 产生事件的按键键值(在Qt::Key枚举查看, 通常字符于对应ascll码值是一致的)
      • modifiers – 修饰符,用以判断是否是组合按键,有以下值(可以用位或进行组合)
        • Qt::NoModifier
        • Qt::ShiftModifier --> shift键被同时按下
        • Qt::ControlModifier --> ctrl键被同时按下,以下类似
        • Qt::AltModifier
        • Qt::MetaModifier --> win键
        • Qt::KeypadModifier
        • Qt::GroupSwitchModifier
      • text --> 字符信息,当key是一个字符输入时,则在相应的则在焦点组件输入字符信息,否则text为无效
      • (例如:key = Qt::key_0,则焦点输入组件输入字符’0’,key = Qt::Key_backspace,则text无效,而是表示退格键按下)
      • autorep --> 是否是自动重复按键
      • count --> 事件中涉及按键的数量
  • 成员函数:
    • bool matches(QKeySequence::StandardKey key) const
      • 匹配按键所触发的标准行为(例如:复制(QKeySequence::Copy))
      • 匹配成功返回true,否则返回false
  • 事件处理函数:
    • QWidget::keyPressEvent(QKeyEvent *) --> 有按键被按压
    • QWidget::keyReleaseEvent(QKeyEvent *) --> 有按键被释放
  • 软键盘制作思路:
    • 按钮布局,定义槽函数(最好使用按钮组, 或者直接派生QPushButton在自定义的按钮中定义槽函数,避免为每个按钮都定义槽函数)
    • setFocusPolicy(Qt::NoFocus)设置软件盘按钮的焦点策略为Qt::NoFocus, 防止点击软键盘按键后输入框失去焦点,无法正常输入
    • 在槽函数中根据所按下的按钮创建相应的QKeyEvent事件对象keyeventobj
    • void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)函数向焦点组件发送按键事件
      • 参数说明:
        • receiver为事件接收的对象(这里为对应按钮)
        • event创建的键盘事件keyeventobj(Event为QKeyEvent的基类,所以是兼容的)
        • priority事件优先级(APPlication对象会对所有产生的事件按优先级排序,顺序派发处理)
    • 可以通过QApplication::FocusWidget()获得当前焦点组件(例如TextEidt类对象)
  • 自定义键盘于鼠标的组合键(eg.Ctrl+鼠标左键)事件思路:
    • 自定义鼠标按压事件
    • 在进入鼠标按压事件处理函数中做如下判断:
      • 判断鼠标按下的具体键
      • 判断键盘按键修饰符(通过函数QApplication::keyboardModifiers()可返回按下的Modifiers)
    • 如果判断为Ctrl和鼠标左键按下,则执行相应的操作

改变焦点的方式以及策略(focusPolicy)

  • 改变方式:
    • Tab键或者Shift+Tab
    • 鼠标点击
    • 鼠标滚轮
    • 代码setFocus()
  • focusPolicy:
    • Qt::TabFouc --> 可通过Tab获得焦点
    • Qt::ClickFocus --> 可通过点击获得焦点
    • Qt::StrongFocus --> 可通过上述两种方式获得焦点
    • Qt::NoFocus --> 不能通过上述方式获得焦点,但setFocus()仍然有效

简单软键盘(部分按键)制作代码:

  • 效果:
    【QT学习】QKeyEvent键盘事件制作简单软件盘

自定义派生PushButton类的头文件btkey.h

#ifndef BTKEY_H
#define BTKEY_H

#include <QPushButton>
#include <QKeyEvent>
#include <QApplication>
#include <QObject>
#include "mykeyboard.h"

#include <QDebug>

class Btkey : public QPushButton
{
    Q_OBJECT

public:
    // 用两个bool静态成员来表示键盘的caps和shift键是否按下
    static bool capstatus;
    static bool shiftstatus;

    Btkey(QWidget *parent = nullptr);
    ~Btkey();

private slots:
    void handler_slot(bool k);
};

#endif // BTKEY_H

自定义派生PushButton类的源文件btkey.cpp

#include "btkey.h"

bool Btkey::capstatus = false;
bool Btkey::shiftstatus = false;

Btkey::Btkey(QWidget *parent) :
    QPushButton(parent)
{
    // 将按钮的颜色置为半透明的蓝色
    this->setStyleSheet("background-color: rgba(153, 215, 255, 150);");
    // 设置焦点获得策略
    this->setFocusPolicy(Qt::NoFocus);

    // 链接槽函数
    connect(this, SIGNAL(clicked(bool)), this, SLOT(handler_slot(bool)));
}

Btkey::~Btkey()
{
    this->destroy();
}

void Btkey::handler_slot(bool k)
{
    QApplication::keyboardModifiers();
    auto *objfous = QApplication::focusWidget();
    bool ok;
    int key = this->text().toInt(&ok, 16);
    QString text(this->text());

    qDebug() << this->text();
    if(this->text() == "CapsLK"){
        qDebug() << "按下CapsLk键";
        capstatus = k;
        qobject_cast<MyKeyBoard *>(this->parent())->letterToggle();
        text = "";
    }else if(this->text() == "Shift"){
        qDebug() << "按下Shift键";
        shiftstatus = k;
        qobject_cast<MyKeyBoard *>(this->parent())->letterToggle();
        key = Qt::Key_Shift;
        text = "";
    }else if(this->text() == "Enter"){
        qDebug() << "按下Enter键";
        key = Qt::Key_Enter;
    }else if(this->text() == "Backspace"){
        qDebug() << "按下BackSpace键";
        key = Qt::Key_Backspace;
    }else if(this->text() == "Tab"){
        qDebug() << "按下Tab键";
        key = Qt::Key_Tab;
    }else{
        qDebug() << "按下数字、字母或符号";
    }
    // 创建相应的按键事件对象
	QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, key
			 , Qt::NoModifier, text
			 , false, 1);

	// fousWidget() 返回光标所在的对象
    // 派发事件
	QCoreApplication::postEvent(objfous, event);

    // 如果shift被按下,且又按下其他键,将让shift键弹起
	if(shiftstatus && key != Qt::Key_Shift){
	    shiftstatus = false;
	    qobject_cast<MyKeyBoard *>(this->parent())->shift_recover();
	    qobject_cast<MyKeyBoard *>(this->parent())->letterToggle();
	}
}

软键盘类的头文件mykeyboard.h

#ifndef MYKEYBOARD_H
#define MYKEYBOARD_H

#include <QWidget>
#include "btkey.h"
#include <QButtonGroup>
#include <QBrush>

QT_BEGIN_NAMESPACE
namespace Ui { class MyKeyBoard; }
QT_END_NAMESPACE

class MyKeyBoard : public QWidget
{
    Q_OBJECT

public:
    MyKeyBoard(QWidget *parent = nullptr);
    ~MyKeyBoard();

    void letterToggle(void);
    void shift_recover(void);

private slots:

private:
    Ui::MyKeyBoard *ui;
    QButtonGroup *Btletter;
    QList<QPushButton *> *Btlist;
};
#endif // MYKEYBOARD_H

软键盘类的源文件mykeyboard.cpp

#include "mykeyboard.h"
#include "ui_mykeyboard.h"

MyKeyBoard::MyKeyBoard(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyKeyBoard)
    , Btletter(new QButtonGroup(this))
    , Btlist(new QList<QPushButton *>())
{
    ui->setupUi(this);
    /* 按钮的布局以及部分属性定义(autorepeat属性,让按下持续输出)在uidesigner中设计*/

    // 将字母按键放到一个按键组方便大小写切换
    {
        Btletter->addButton(ui->key_a, 0);
        Btletter->addButton(ui->key_b, 1);
        Btletter->addButton(ui->key_c, 2);
        Btletter->addButton(ui->key_d, 3);
        Btletter->addButton(ui->key_e, 4);
        Btletter->addButton(ui->key_f, 5);
        Btletter->addButton(ui->key_g, 6);
        Btletter->addButton(ui->key_h, 7);
        Btletter->addButton(ui->key_i, 8);
        Btletter->addButton(ui->key_j, 9);
        Btletter->addButton(ui->key_k, 10);
        Btletter->addButton(ui->key_l, 11);
        Btletter->addButton(ui->key_n, 12);
        Btletter->addButton(ui->key_m, 13);
        Btletter->addButton(ui->key_o, 14);
        Btletter->addButton(ui->key_p, 15);
        Btletter->addButton(ui->key_q, 16);
        Btletter->addButton(ui->key_r, 17);
        Btletter->addButton(ui->key_s, 18);
        Btletter->addButton(ui->key_t, 19);
        Btletter->addButton(ui->key_u, 20);
        Btletter->addButton(ui->key_v, 21);
        Btletter->addButton(ui->key_w, 22);
        Btletter->addButton(ui->key_x, 23);
        Btletter->addButton(ui->key_y, 24);
        Btletter->addButton(ui->key_z, 25);
    }

    // 将shift和capslk键设置为可校验(按下不自动弹起)
    ui->key_capslk->setCheckable(true);
    ui->key_shift->setCheckable(true);

    // 设置背景为透明
    this->setAutoFillBackground(true);
    QPalette palette;
    palette.setBrush(QPalette::Background, QBrush(QColor(0,0,0,0)));
    this->setPalette(palette);
}

MyKeyBoard::~MyKeyBoard()
{
    delete ui;
}

// 实现CapsLk和Shift键的大小写翻转
void MyKeyBoard::letterToggle()
{
    for(int i = 0; i < 26; i++){
        QString c = Btletter->button(i)->text();
        // 等价于逻辑异或
        if(Btkey::capstatus ^ Btkey::shiftstatus)
            Btletter->button(i)->setText(c.toUpper());
        else
            Btletter->button(i)->setText(c.toLower());
    }
}

void MyKeyBoard::shift_recover()
{
    ui->key_shift->setChecked(false);
}
  • 使用:
    • 将键盘类的相关头文件和源文件(Btkey和MyKeyBoard)添加到工程
    • 在designer界面中添加Widget组件
    • 将Widget组件提升为MyKeyBoard类
上一篇:从 0 学习 Python 0 - 100 大合集总结


下一篇:UI自动化获取元素封装