碎碎念
这次还是在自己写玩具的时候碰到了一点难题然后花了大量时间所以想着发一篇博文记录一下
这个东西我写了两天才写出来
实现组合按键的检测,也就是实现当数个按键在连续 的 一段时间 内 _按顺序_按下并按住时才触发即返回true
我写了注释&&注释没删
因为涉及到时间尺度的变化,所以显然不可能用流式存储的方式存储一系列按键状态来解决”一定时间中”这个持续变量的问题。
同时由于按键监测的要求是在 一段时间内 按顺序 按住 组合键中声明的按键,所以可以通过一个可以变动的下标来表示在当前时刻”合法”的按键簇(雾)
总之就是灵光乍现什么的然后我们在最开始有了这样一个类的声明
class FnKeys:
__i = 0
def __init__(self, mod: str, keys: [int]):
if type(keys) == int:
keys = [keys]
有了下标,那相应的就应该让下标能有办法够增长。为了能够实现 同时按下多个按键能够被检测到,我想到用下面这一段代码|来实现
while self.__i < len(self.keys):
if keyMap[self.keys[self.__i]]:
self.__i += 1
else:
break
记住这个坑。就是因为这个部分,害的我把check函数重新写了好多遍才找出问题
因为要检测的是组合键,所以检测用的函数需要传入用来表示按键映射的列表或数组。于是我们有了抽象函数|·+·|
def check(self, keyMap: [int]):
先声明一下,这个类的check方法是 基于 主循环写的,所以check函数所做的其实必须是帧检查(我把循环跑一遍当做一帧),不能写成抢占式检测最大的难点。
由此我产生了对输入组合键可能性的思考…折寿中…
经过一段时间的思考后,我想出来以下四种情况
不同状态1234上一帧0 – ★★ 0 –★0- – -这一帧★★★★★★- – — – -期望结果FalseFalseTrueTrue
图形解释:
- 为释放状态,按键松开;
0 为按住状态,按键被按住;
★ 为任意状态,此时按键处于薛定谔态(即不管这个键的状态)
一串图形代表组合键中声明的多个按键在同一时刻的状态
当时我的思路是依据下标所在的键(当前键)做分割,分别处理声明组合键列表 self.keys
中当前键之前的部分(前键,前键下标小于当前键)和之后的部分(后键,后键下标大于当前键),然后分类讨论。
对前键的判断直接关系到状态1、3、4的结果。
如果组合键生效,那么显然前键必须全部都被按住。同时如果前键中有任意键被松开,则组合键失效。对应以下代码
j = self.__i - (self.__i == len(self.keys))
while j >= 0:
if keyMap[self.keys[j]]:
j -= 1
else:
break
if j != -1:
self.__lock_a = False
else:
self.__lock_a = self.__lock_b
对后键的判断直接影响状态1,2,3三种结果
如果组合键生效,则显然后键不存在,此时不考虑后键即可。
但是在按键未全部按下(比如组合键ctrl+v键按住了ctrl键但是v键没按下或者v键按下了但ctrl键没有按下)时,后键中必须全部都没有按下才允许当前键向后推进,否则容易出现预料之外的状况(比如只按下v键但结果产生了ctrl+v的效果)。
后键代码如下
if not self.__lock_a:
j = self.__i + 1
while j < len(self.keys):
if not keyMap[self.keys[j]]:
j += 1
else:
break
self.__lock_b = j == len(self.keys)
else:
j = self.__i + 1
if self.__lock_b:
while j < len(self.keys):
if keyMap[self.keys[j]]:
j += 1
else:
j += 1
break
while j < len(self.keys):
if not keyMap[self.keys[j]]:
j += 1
else:
self.__lock_b = False
break
else:
self.__lock_b = True
期间还有一些东西我忘记了,但反正是很重要的细节,不过最后的代码成品是对的,如果和先前的分析有什么不一样的地方, 以成品代码为准。
放在最后的成品类
"""
Time: 2022/6/25
Author: Zhai H***g(ZII)
Version: alpha-0.0.1
File: 抽象-事件-栈.py
Describe: 组合键按键的帧检测
"""
class FnKeys:
__i = 0
__lock_a = True
__lock_b = True
def __init__(self, mod: str, keys: [int]):
if type(keys) == int:
keys = [keys]
def check(self, keyMap) -> bool:
"""装饰:有序"""
def rollBack():
i = 0
while i < len(self.keys):
if keyMap[self.keys[i]]:
i += 1
else:
break
return i
j = self.__i - (self.__i == len(self.keys))
while j >= 0:
if keyMap[self.keys[j]]:
j -= 1
else:
break
if j != -1:
self.__lock_a = False
self.__i = rollBack()
else:
self.__lock_a = self.__lock_b
if not self.__lock_a:
j = self.__i + 1
while j < len(self.keys):
if not keyMap[self.keys[j]]:
j += 1
else:
break
self.__lock_b = j == len(self.keys)
else:
j = self.__i + 1
if self.__lock_b:
while j < len(self.keys):
if keyMap[self.keys[j]]:
j += 1
else:
j += 1
break
while j < len(self.keys):
if not keyMap[self.keys[j]]:
j += 1
else:
self.__lock_b = False
break
else:
self.__lock_b = True
while self.__i < len(self.keys) and self.__lock_a and self.__lock_b:
if keyMap[self.keys[self.__i]]:
self.__i += 1
else:
break
if self.__i < len(self.keys) and self.__lock_a and self.__lock_b:
self.__i = rollBack()
if self.__i == len(self.keys) and self.__lock_a and self.__lock_b:
return True
else:
return False
Original: https://blog.csdn.net/qq_46181326/article/details/125459444
Author: 一只正在学编程的仓鼠
Title: 【组合键检测】一个用来实现组合键/快捷键的帧检测算法/类
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/783094/
转载文章受原作者版权保护。转载请注明原作者出处!