1.思路
想写个判断哪些方向键同时按下的逻辑,结果发现 Qt 的按键事件只能取到单个键值,而 QKeyEvent::modifiers() 又只能获取 Ctrl 或者 Shift 这种辅助按键。一番百度之后,发现可以使用容器保存按键值,在 keyPressEvent 添加按键值,在 keyReleaseEvent 移除按键值。
不过单单处理按键的按下和弹起还不够,还需要注意一些事项:
A.弹起其中一个按键时,按键事件的触发会停顿一下。所以,不能在按键事件里直接处理逻辑,需要加个定时器来遍历我们的键值容器;
B.按键长按时会重复触发按下和弹起两个事件,这可能导致我们的键值容器在遍历时值不对(比如长按触发按键事件,导致定时器触发时我们的容器正好弹出键值就为空了)。所以,我们要单独判断下 QKeyEvent 的 isAutoRepeat,如果是自动重复触发就不处理。
实现效果,以移动方块为例(两个方向键同时按下就是斜着移动):
分别展示 QWidget 和 QML 的示例。
2.QWidget 代码#ifndef UNIT4MOVE_H
#define UNIT4MOVE_H
#include
#include
#include
#include
#include
//按键移动物体
class Unit4Move : public QOpenGLWidget, protected QOpenGLFunctions_4_0_Compatibility
{
Q_OBJECT
public:
explicit Unit4Move(QWidget *parent = nullptr);
protected:
//设置OpenGL资源和状态。在第一次调用resizeGL或paintGL之前被调用一次
void initializeGL() override;
//渲染OpenGL场景,每当需要更新小部件时使用
void paintGL() override;
//设置OpenGL视口、投影等,每当尺寸大小改变时调用
void resizeGL(int width, int height) override;
//按键按下
void keyPressEvent(QKeyEvent *event) override;
//按键释放
void keyReleaseEvent(QKeyEvent *event) override;
//设置切换显示的时候获取焦点
void showEvent(QShowEvent *event) override;
private:
//顶点列表
QList vertexList;
//移动
float xOffset=0;
float yOffset=0;
//当前按键按下的列表
//因为Qt按键事件只能判断出一个键值和辅助键值的组合,
//所以自己保存按下的按键
QSet pressedKeys;
//刷新定时器
QTimer *updateTimer;
};
#endif // UNIT4MOVE_H
#include "Unit4Move.h"
#include
#include
#include
#include
#include
Unit4Move::Unit4Move(QWidget *parent)
: QOpenGLWidget(parent)
{
//默认没得焦点,没法接收按键
setFocusPolicy(Qt::StrongFocus);
//多个按键按下还有一个问题,就是最后那个按键弹起后就不会重复触发了
//所以刷新我们可以用定时器来判断容器列表,release时判断为空就关,press就开
updateTimer=new QTimer(this);
connect(updateTimer,&QTimer::timeout,[this]{
//qDebug()isActive())
updateTimer->start(100);
}
void Unit4Move::keyReleaseEvent(QKeyEvent *event)
{
QOpenGLWidget::keyReleaseEvent(event);
//按键释放,从容器中移除,如果是长按触发的repeat就不判断
if(!event->isAutoRepeat())
pressedKeys.remove(event->key());
if(pressedKeys.isEmpty()){
updateTimer->stop();
}
}
void Unit4Move::showEvent(QShowEvent *event)
{
QOpenGLWidget::showEvent(event);
setFocus();
}
3.QML 代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("GongJianBo")
//存储当前按下的键值,使用ES6的集合类型
property variant pressedKeys:new Set()
Rectangle{
id: item
//anchors.centerIn: parent
x:100
y:100
width: 100
height: 100
color: "green"
focus: true
//按键按下
Keys.onPressed: {
//键值放入set
if(!event.isAutoRepeat){
pressedKeys.add(event.key)
}
if(!timer.running){
timer.start()
}
}
//按键释放
Keys.onReleased: {
//键值弹出set
if(!event.isAutoRepeat){
pressedKeys.delete(event.key)
}
if(pressedKeys.size
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?