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文库