Qt 多按键高频触发,无延迟

文章介绍了如何在Qt中重写默认的按键事件处理,以实现在短时间内连续按键时能持续发送信号,提高交互体验。通过使用QKeyEvent和QTimer,实现了高频触发效果并提供可配置的间隔功能。
摘要由CSDN通过智能技术生成

Qt 默认按键触发时间都是按压一会才会持续发送信号,导致有种很笨拙的感觉,不流畅丝滑,无法实现一些需要的效果,这样就得重写一下相应的函数

protected:
    virtual void keyPressEvent(QKeyEvent *event);
    virtual void keyReleaseEvent(QKeyEvent *event);

void KeyboardHighFrequencyTriggerWidget::keyPressEvent(QKeyEvent *event)
{
    if(!event->isAutoRepeat()){
        this->v_pressKeyList.append(event->key());
        emit this->pressed(this->v_pressKeyList);
    }
}

void KeyboardHighFrequencyTriggerWidget::keyReleaseEvent(QKeyEvent *event)
{
    if(!event->isAutoRepeat()){
        this->v_pressKeyList.removeOne(event->key());
        emit this->released(this->v_pressKeyList);
    }
}

QKeyEvent::isAutoRepeat(): 用于判断按键是否已经触发

按下的加入list,松开的移出list,并且触发定义的两个信号

private:signals:
    void pressed(QList<int>);
    void released(QList<int>);

    this->connect(this,&KeyboardHighFrequencyTriggerWidget::pressed,this,[&](QList<int>_)
    {
        if(!_.isEmpty())
        {
            if(!this->v_timer_press.isActive())
            {
                this->v_timer_press.start();
            }
        }
    });

    this->connect(this,&KeyboardHighFrequencyTriggerWidget::released,this,[&](QList<int>_)
    {
        if(_.isEmpty())
        {
            this->v_timer_press.stop();
            emit this->releasedKeyList();
        }
    });

绑定信号,触发QTimer,让QTimer持续发送timeout信号,以实现高频触发效果

    this->connect(&this->v_timer_press,&QTimer::timeout,this,[&]()
    {
        emit this->pressedKeyList(this->v_pressKeyList);
    });

完整代码

KeyboardHighFrequencyTriggerWidget .h

#ifndef KEYBOARDHIGHFREQUENCYTRIGGERWIDGET_H
#define KEYBOARDHIGHFREQUENCYTRIGGERWIDGET_H

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

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

    /**
     * @brief setAutoGetFocus 是否自动夺取焦点
     */
    void setAutoGetFocus(bool);

    /**
     * @brief setInterval 设置触发频率
     */
    void setInterval(int);

    /**
     * @brief setFocusInterval 设置夺取焦点频率
     */
    void setFocusInterval(int);

public:signals:
    /**
     * @brief pressedKeyList 持续发送触发信号
     * @param pressKeyList 按下的KEY值表
     */
    void pressedKeyList(QList<int> pressKeyList);

    /**
     * @brief releasedKeyList 当没有按键按下就会触发该型号
     */
    void releasedKeyList();

protected:
    virtual void keyPressEvent(QKeyEvent *event);
    virtual void keyReleaseEvent(QKeyEvent *event);

private:signals:
    void pressed(QList<int>);
    void released(QList<int>);

private:
    QList<int> v_pressKeyList;//记录目前按下的按键

    QTimer v_timer_press;//用于持续触发press信号
    QTimer v_timer_focus;//用于获取焦点
};

#endif // KEYBOARDHIGHFREQUENCYTRIGGERWIDGET_H

KeyboardHighFrequencyTriggerWidget .cpp

#include "KeyboardHighFrequencyTriggerWidget.h"
#include <QDebug>

KeyboardHighFrequencyTriggerWidget::KeyboardHighFrequencyTriggerWidget(QWidget *parent) : QWidget(parent)
{
    this->setFocus();
    this->v_timer_press.setInterval(10);
    this->v_timer_focus.setInterval(20);

    this->connect(&this->v_timer_focus,&QTimer::timeout,this,[&]()
    {
        this->setFocus();
    });

    this->v_timer_focus.start();

    this->connect(&this->v_timer_press,&QTimer::timeout,this,[&]()
    {
        emit this->pressedKeyList(this->v_pressKeyList);
    });

    this->connect(this,&KeyboardHighFrequencyTriggerWidget::pressed,this,[&](QList<int>_)
    {
        if(!_.isEmpty())
        {
            if(!this->v_timer_press.isActive())
            {
                this->v_timer_press.start();
            }
        }
    });

    this->connect(this,&KeyboardHighFrequencyTriggerWidget::released,this,[&](QList<int>_)
    {
        if(_.isEmpty())
        {
            this->v_timer_press.stop();
            emit this->releasedKeyList();
        }
    });
}

void KeyboardHighFrequencyTriggerWidget::setAutoGetFocus(bool _)
{
    if(_ == false)
    {
        this->v_timer_focus.stop();
    }
    else
    {
        this->v_timer_focus.start();
    }
}

void KeyboardHighFrequencyTriggerWidget::setInterval(int _)
{
    this->v_timer_press.setInterval(_);
}

void KeyboardHighFrequencyTriggerWidget::setFocusInterval(int _)
{
    this->v_timer_focus.setInterval(_);
}

void KeyboardHighFrequencyTriggerWidget::keyPressEvent(QKeyEvent *event)
{
    if(!event->isAutoRepeat()){
        this->v_pressKeyList.append(event->key());
        emit this->pressed(this->v_pressKeyList);
    }
}

void KeyboardHighFrequencyTriggerWidget::keyReleaseEvent(QKeyEvent *event)
{
    if(!event->isAutoRepeat()){
        this->v_pressKeyList.removeOne(event->key());
        emit this->released(this->v_pressKeyList);
    }
}

封装成类,可以供其他控件调用,但是需要关注的第一就是,如果KeyboardHighFrequencyTriggerWidget获取不到焦点的话,就不会触发按键事件,因此内置了持续获取焦点的方法

效果图

测试DEMO:【免费】Qt多按键高频触发DEMO资源-CSDN文库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值