1.Qt的键盘事件:
voidkeyReleaseEvent(QKeyEvent *);//按键释放事件voidkeyPressEvent(QKeyEvent *);//按键按下事件
2.Qt可以响应的按键事件:
单个按键、组合键(例如:crtl+c)
注意:
- 当单个按键按下释放后,按键事件还会停顿一下,所以我们不能在按键事件里面直接处理逻辑。--------借助定时器。
- 如果我们想响应多个按键同时按下的效果,单凭这键盘事件是没办法实现的。-------借助容器
3.借助定时器和容器,实现多个按键按下的同时响应
- 以WASD四按键为例,实现QLabel控件的丝滑移动。首先准备一个容器用于存放按下按键的key
QList<int> keys;//头文件中添加成员
- 定义一个定时器用于遍历容器
QTimer* keyRespondTimer;//头文件中添加成员keyRespondTimer =newQTimer(this);//构造函数中创建定时器对象,并连接信号槽connect(keyRespondTimer,&QTimer::timeout,this,&Widget::slotTimeOut);
- 处理按键按下事件
voidWidget::keyPressEvent(QKeyEvent *event){if(!event->isAutoRepeat())//判断如果不是长按时自动触发的按下,就将key值加入容器 keys.append(event->key());if(!keyRespondTimer->isActive())//如果定时器不在运行,就启动一下 keyRespondTimer->start(4);}
- 处理按键释放事件
voidWidget::keyReleaseEvent(QKeyEvent *event){if(!event->isAutoRepeat())//判断如果不是长按时自动触发的释放,就将key值从容器中删除 keys.removeAll(event->key());if(keys.isEmpty())//容器空了,关闭定时器 keyRespondTimer->stop();}
注意点:
if(!event->isAutoRepeat())
,增加这一判断是为了避免在按键长按期间一直触发按键事件,对同一键值一直做容器追加和删除操作。这显然是没必要的耗时操作,我们只需要保证在长按期间,那个按键的键值key一直在容器里就好了。
- 遍历key值容器,实现多个按键的同时响应
voidWidget::slotTimeOut(){foreach(int key, keys){switch(key){case Qt::Key_W: ui->label->move(ui->label->x(), ui->label->y()-1);break;case Qt::Key_A: ui->label->move(ui->label->x()-1, ui->label->y());break;case Qt::Key_S: ui->label->move(ui->label->x(), ui->label->y()+1);break;case Qt::Key_D: ui->label->move(ui->label->x()+1, ui->label->y());break;default:break;}}}
4.效果图
5.源码
#ifndefWIDGET_H#defineWIDGET_H#include<QWidget>#include<QTimer>#include<QKeyEvent>
QT_BEGIN_NAMESPACE
namespace Ui {classWidget;}
QT_END_NAMESPACE
classWidget:publicQWidget{
Q_OBJECT
public:Widget(QWidget *parent =nullptr);~Widget();protected:voidkeyPressEvent(QKeyEvent *event)override;voidkeyReleaseEvent(QKeyEvent *event)override;private:
Ui::Widget *ui;
QList<int> keys;
QTimer* keyRespondTimer;voidslotTimeOut();};#endif// WIDGET_H
#include"widget.h"#include"ui_widget.h"Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget){
ui->setupUi(this);
keyRespondTimer =newQTimer(this);connect(keyRespondTimer,&QTimer::timeout,this,&Widget::slotTimeOut);}Widget::~Widget(){delete keyRespondTimer;delete ui;}voidWidget::keyPressEvent(QKeyEvent *event){if(!event->isAutoRepeat())//判断如果不是长按时自动触发的按下,就将key值加入容器
keys.append(event->key());if(!keyRespondTimer->isActive())//如果定时器不在运行,就启动一下
keyRespondTimer->start(4);}voidWidget::keyReleaseEvent(QKeyEvent *event){if(!event->isAutoRepeat())//判断如果不是长按时自动触发的释放,就将key值从容器中删除
keys.removeAll(event->key());if(keys.isEmpty())//容器空了,关闭定时器
keyRespondTimer->stop();}voidWidget::slotTimeOut(){foreach(int key, keys){switch(key){case Qt::Key_W:
ui->label->move(ui->label->x(), ui->label->y()-1);break;case Qt::Key_A:
ui->label->move(ui->label->x()-1, ui->label->y());break;case Qt::Key_S:
ui->label->move(ui->label->x(), ui->label->y()+1);break;case Qt::Key_D:
ui->label->move(ui->label->x()+1, ui->label->y());break;default:break;}}}
版权归原作者 Jerich morningStar 所有, 如有侵权,请联系我们删除。