2025年4月15日 星期二 乙巳(蛇)年 正月十六 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

使用Python实现一个按键精灵

时间:08-23来源:作者:点击数:35

按键精灵想必很多人都玩过,使用录制功能将鼠标和键盘的操作录制下来,录制好后就可以通过回放自动执行之前录制的操作,可以设置重复执行的次数,这样就可以将一些重复的劳动交给脚本自动化去完成。使用Python编写一个和脚本精灵一样的程序非常简单,并且代码量足够少,好处是可以不再依赖按键精灵,像我这种有轻微洁癖的程序猿就喜欢自己动手实现,依赖Python的为所欲为的特性,可以任意编码让自己的按键精灵更加强大。

按键精灵的实现可以拆解分为录制和回放两个步骤,对应到Python程序的实现也可以分为两步:

1.监听鼠标键盘的事件和坐标,写入到文件中记录起来。

2.读取监听时写入的文件,执行文件中的坐标和事件操作。

要实现这两个功能,得先从基础开始。我把任务拆解成两大部分,鼠标和键盘属于不同的两个输入设备,所以分开实现“鼠标精灵”和“键盘精灵”两个程序,最后融合这两个模块实现一个相对完整的按键精灵。

Python操作键盘鼠标的库推荐pynput这个库、地址:

https://pypi.org/project/pynput/

鼠标事件监听
  • from pynput import mouse
  • # 鼠标移动事件
  • def on_move(x, y):
  • print('[Move]', (x, y))
  • # 鼠标点击事件
  • def on_click(x, y, button, pressed):
  • print('[Click]', (x, y, button.name, pressed))
  • # 鼠标滚动事件
  • def on_scroll(x, y, x_axis, y_axis):
  • print('[Scroll]', (x, y, x_axis, y_axis))
  • # 监听事件绑定
  • with mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
  • listener.join()

onMove(x,y)函数接收鼠标当前的x轴和y轴坐标,启动程序并移动鼠标时,就会调用该方法。

on_click(x, y, button, pressed)函数接收鼠标的点击事件,x和y为当前点击事件的鼠标坐标,button参数对象的name属性值为left或者right,通过该属性值可以判断是鼠标的左键还是右键产生的点击事件,pressed参数值为True时表示当前鼠标左或右键按压,False时表示鼠标左或右键抬起事件。

on_scroll(x, y, x_axis, y_axis)接收四个参数,前两个参数依旧是当前事件的鼠标坐标轴,x_axis的值>0表示向上,<0表示向下,同样的y_axis的负值和正值代表左滑和右滑状态。

鼠标事件执行
  • from pynput.mouse import Button, Controller
  • import time
  • # 获取鼠标对象
  • mouse = Controller()
  • # 输出鼠标当前的坐标
  • print(mouse.position)
  • # 将新的坐标赋值给鼠标对象
  • mouse.position = (100, 500)
  • for index in range(0, 30):
  • # 鼠标移动到指定坐标轴
  • mouse.move(index, -index)
  • print(mouse.position)
  • time.sleep(0.01)
  • for index in range(0, 30):
  • # 鼠标移动到指定坐标轴
  • mouse.move(-index, index)
  • print(mouse.position)
  • time.sleep(0.01)
  • # 鼠标右键按下
  • mouse.press(Button.right)
  • time.sleep(0.01)
  • # 鼠标右键抬起
  • mouse.release(Button.right)
  • # 鼠标左键点击
  • mouse.click(Button.left, 1)
  • # 鼠标滚轮滚动距离500
  • mouse.scroll(0, 500)

和鼠标事件监听一样,对应的我们可以操作鼠标的各种事件:移动、左/右按压、左/右抬起、左/右点击、上下左右滚动

上面代码中的mouse.move(x,y)函数,表示从当前鼠标位置进行位移的距离,x和y的值是以当前位置为0点开始算的。

而且不能简单的用坐标轴去相减得到位移距离,所以后续的程序我会使用mouse.position = (x, y)这个函数来操作鼠标的移动,

这个函数可以将鼠标设置到指定位置,只要我们记录之前的鼠标移动轨迹,就可以通过读取之前的记录文件按顺序重新对鼠标进行赋值操作。达到回放的效果。

带录制回放功能的鼠标精灵

结合鼠标事件的监听和执行,并且将事件记录到文件中,再加上Python自带的GUI,就可以写出一个简单的鼠标精灵了。

实现思路:

  1. 定义一个json格式的对象来统一不同鼠标事件的内容格式
  • {
  • "name":"mouse",
  • "event":"click",
  • "target":"left",
  • "action":true,
  • "location":{
  • "x":"0",
  • "y":"0"
  • }
  • }

鼠标事件的name值为mouse,考虑到后续还有可能会有其他设备的事件,比如键盘事件。

鼠标的事件为点击事件,将event赋值为click

target表示目标,点击了鼠标左键,所以目标值为left

action表示动作,鼠标点击分为按压和抬起,true表示抬起。

location的值包含一个json对象,里面为当前事件鼠标的x和y坐标。

鼠标的移动和滑动事件以此类推,用同样的模板格式进行记录。

  1. 将记录的数据写入到文件中
  2. 执行回放时通过逐行读取文件,解析文件中的json数据通过nameeventlocation等值进行事件执行。

之所以选择json时因为解析起来比较方便。当然你也可以使用数据库,比如SQLite等,或者自己定义一套自己的格式。

json的存储方式有太多的冗余字符了,空间占用目前不是考虑的首要因素,这里先用最快的方式实现它。

GUI用了Python自带的tkinter库,为了防止UI阻塞,所以使用了多线程,同样是Python自带库threading

整个实现其实只用了一个三方库 pynput

鼠标事件的监听录制和执行回放的完整代码如下:

  • import json
  • import threading
  • import time
  • import tkinter
  • from pynput import mouse
  • from pynput.mouse import Button, Controller
  • # 鼠标动作模板
  • def mouse_action_template():
  • return {
  • "name": "mouse",
  • "event": "default",
  • "target": "default",
  • "action": "default",
  • "location": {
  • "x": "0",
  • "y": "0"
  • }
  • }
  • # 鼠标动作监听
  • class MouseActionListener(threading.Thread):
  • def __init__(self, file_name):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'w', encoding='utf-8') as file:
  • # 鼠标移动事件
  • def on_move(x, y):
  • template = mouse_action_template()
  • template['event'] = 'move'
  • template['location']['x'] = x
  • template['location']['y'] = y
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 鼠标点击事件
  • def on_click(x, y, button, pressed):
  • template = mouse_action_template()
  • template['event'] = 'click'
  • template['target'] = button.name
  • template['action'] = pressed
  • template['location']['x'] = x
  • template['location']['y'] = y
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 鼠标滚动事件
  • def on_scroll(x, y, x_axis, y_axis):
  • template = mouse_action_template()
  • template['event'] = 'scroll'
  • template['location']['x'] = x_axis
  • template['location']['y'] = y_axis
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • with mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
  • listener.join()
  • # 鼠标动作执行
  • class MouseActionExecute(threading.Thread):
  • def __init__(self, file_name):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'r', encoding='utf-8') as file:
  • mouse_exec = Controller()
  • line = file.readline()
  • time.sleep(0.01)
  • while line:
  • obj = json.loads(line)
  • if obj['name'] == 'mouse':
  • if obj['event'] == 'move':
  • mouse_exec.position = (obj['location']['x'], obj['location']['y'])
  • time.sleep(0.01)
  • elif obj['event'] == 'click':
  • if obj['action']:
  • if obj['target'] == 'left':
  • mouse_exec.press(Button.left)
  • else:
  • mouse_exec.press(Button.right)
  • else:
  • if obj['target'] == 'left':
  • mouse_exec.release(Button.left)
  • else:
  • mouse_exec.release(Button.right)
  • time.sleep(0.01)
  • elif obj['event'] == 'scroll':
  • mouse_exec.scroll(obj['location']['x'], obj['location']['y'])
  • time.sleep(0.01)
  • line = file.readline()
  • def button_onClick(action):
  • m1 = MouseActionListener(file_name='mouse.action')
  • m2 = MouseActionExecute(file_name='mouse.action')
  • if action == 'listener':
  • if startListenerBtn['text'] == '录制':
  • m1.start()
  • startListenerBtn['text'] = '录制中...关闭程序停止录制'
  • startListenerBtn['state'] = 'disabled'
  • elif action == 'execute':
  • if startExecuteBtn['text'] == '回放':
  • m2.start()
  • startExecuteBtn['text'] = '回放中...关闭程序停止回放'
  • startExecuteBtn['state'] = 'disabled'
  • if __name__ == '__main__':
  • root = tkinter.Tk()
  • root.title('鼠标精灵-蓝士钦')
  • root.geometry('200x200+400+100')
  • startListenerBtn = tkinter.Button(root, text="录制", command=lambda: button_onClick('listener'))
  • startListenerBtn.place(x=10, y=10, width=180, height=80)
  • startExecuteBtn = tkinter.Button(root, text="回放", command=lambda: button_onClick('execute'))
  • startExecuteBtn.place(x=10, y=110, width=180, height=80)
  • root.mainloop()

按键精灵的鼠标部分到这里就基本完成了。

运行程序,点击录制,然后就可以用你的鼠标在屏幕上一顿操作。然后关闭本程序。

接着重新打开程序,点击回放,就会发现鼠标可以按照之前录制的动作进行自动工作了。

记住千万不要在录制时,还没关闭程序的时候就点击回放,这样会陷入无限循环里面,会导致不停的录制不停的回放。

还有键盘的程序后续补上,程序待完善中,未完待续。

键盘事件监听
  • from pynput import keyboard
  • # 按键按下监听
  • def on_press(key):
  • try:
  • print('press key {0}, vk: {1}'.format(key.char, key.vk))
  • except AttributeError:
  • print('special press key {0}, vk: {1}'.format(key, key.value.vk))
  • # 按键释放监听
  • def on_release(key):
  • if key == keyboard.Key.esc:
  • # 停止监听
  • return False
  • try:
  • print('release key {0}, vk: {1}'.format(key.char, key.vk))
  • except AttributeError:
  • print('special release key {0}, vk: {1}'.format(key, key.value.vk))
  • # 键盘监听
  • with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
  • listener.join()

键盘监听相对于鼠标监听来说,回调的函数只有两个on_press按键按下 和on_release按键释放。

由于pynput这个库对键盘的不同按键事件封装进行了区分,比如普通的数字和字母键按下会进入on_press方法,通过传入的key.char属性值可以得到按键对应在键盘上的字符,但如果是Shift等其他特殊键,就没有char属性,会产生异常。

只要捕获异常后直接通过key就可以取到特殊键对应的字符。我觉得这是pynput做得有点不够优雅的地方。

普通的键有key.vk属性值,代表键盘上字符对应的编码值,特殊键的编码值要通过key.value.vk来取。

键盘事件执行
  • from pynput.keyboard import Key, Controller, KeyCode
  • # 键盘控制对象
  • keyboard = Controller()
  • # 按下 a 键
  • keyboard.press('a')
  • # 释放 a 键
  • keyboard.release('a')
  • # 按下 Shift 键
  • keyboard.press(Key.shift)
  • keyboard.press('b')
  • keyboard.release('b')
  • keyboard.press('c')
  • keyboard.release('c')
  • # 释放 Shift 键
  • keyboard.release(Key.esc)
  • # 按下 Shift 键,然后依次按下其他按键,完成后Shift键自动释放
  • with keyboard.pressed(Key.shift):
  • keyboard.press('d')
  • keyboard.release('d')
  • keyboard.press('e')
  • keyboard.release('e')
  • # 依次按下 python (包括前面的空格)
  • keyboard.type(' python')
  • # 按下 vk值为56的键 shift 键
  • keyboard.touch(KeyCode.from_vk(56), True)
  • keyboard.touch('a', True)
  • keyboard.touch('a', False)
  • # 释放 shift 键
  • keyboard.touch(Key.shift, False)

和监听方法对应,执行键盘的按键方法有press(key)按压 release(key)释放。

除此之外还有touch(key,is_press)函数,key表示要操作的键,is_press 为True时表示按压,为False时表示释放。

无论是哪种按压事件,Key都可以通过其他方式构造,比如知道Shift的vk值为56,那么就可以通过KeyCode.from_vk(56)来构造一个Shift的Key。

通过VK编码构造Key的方式很有用,因为当你要按出一个@符号时,需要同时按住Shift2。通过on_press(key)监听得到的值是一个@符号,如果录制程序录制了一个@符号将无法通过keyboard.press('@')这种方式直接执行。

所以接下来的键盘录制回放程序我将通过定义一个键盘动作模板,然后通过VK值准确的记录每个键以及每个组合键的编码。然后通过keyboard.press(KeyCode.from_vk(vk))进行回放。

带录制回放功能的键盘精灵
  • import json
  • import threading
  • import time
  • import tkinter
  • from pynput import keyboard
  • from pynput.keyboard import Controller, KeyCode
  • # 键盘动作模板
  • def keyboard_action_template():
  • return {
  • "name": "keyboard",
  • "event": "default",
  • "vk": "default"
  • }
  • # 键盘动作监听
  • class KeyboardActionListener(threading.Thread):
  • def __init__(self, file_name):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'w', encoding='utf-8') as file:
  • # 键盘按下监听
  • def on_press(key):
  • template = keyboard_action_template()
  • template['event'] = 'press'
  • try:
  • template['vk'] = key.vk
  • except AttributeError:
  • template['vk'] = key.value.vk
  • finally:
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 键盘抬起监听
  • def on_release(key):
  • if key == keyboard.Key.esc:
  • # 停止监听
  • startListenerBtn['text'] = '录制'
  • startListenerBtn['state'] = 'normal'
  • return False
  • template = keyboard_action_template()
  • template['event'] = 'release'
  • try:
  • template['vk'] = key.vk
  • except AttributeError:
  • template['vk'] = key.value.vk
  • finally:
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 键盘监听
  • with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
  • listener.join()
  • # 键盘动作执行
  • class KeyboardActionExecute(threading.Thread):
  • def __init__(self, file_name):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'r', encoding='utf-8') as file:
  • keyboard_exec = Controller()
  • line = file.readline()
  • time.sleep(3)
  • while line:
  • obj = json.loads(line)
  • if obj['name'] == 'keyboard':
  • if obj['event'] == 'press':
  • keyboard_exec.press(KeyCode.from_vk(obj['vk']))
  • time.sleep(0.01)
  • elif obj['event'] == 'release':
  • keyboard_exec.release(KeyCode.from_vk(obj['vk']))
  • time.sleep(0.01)
  • line = file.readline()
  • startExecuteBtn['text'] = '回放'
  • startExecuteBtn['state'] = 'normal'
  • def button_onClick(action):
  • m1 = KeyboardActionListener(file_name='keyboard.action')
  • m2 = KeyboardActionExecute(file_name='keyboard.action')
  • if action == 'listener':
  • if startListenerBtn['text'] == '录制':
  • m1.start()
  • startListenerBtn['text'] = '录制中...esc停止录制'
  • startListenerBtn['state'] = 'disabled'
  • elif action == 'execute':
  • startListenerBtn.place(x=10, y=10, width=180, height=80)
  • startExecuteBtn = tkinter.Button(root, text="回放", command=lambda: button_onClick('execute'))
  • startExecuteBtn.place(x=10, y=110, width=180, height=80)
  • root.mainloop()

键盘精灵的录制和回放程序到这里以及算是一个基础版本了,可以正常使用。并且新增了esc键监听,当用户点击esc时将会结束录制。

鼠标精灵键盘精灵都可以单独的运行使用。

大多数场景下这两者的功能都会使用到,所以接下来我要实现一个完成的按键精灵,同时包含鼠标和键盘的录制回放功能。

在之前的代码基础上进一步封装。

考虑的基本要素如下:

  1. 记录鼠标和记录键盘的事件采用不同的json模板进行定义,采用响应式对用户的操作进行监听,用户静止不动则不会写入文件。
  2. 同时监听鼠标和键盘,为了避免多线程写同一个文件的锁操作,我将鼠标和键盘的录制记录分为两个不同的文件。
  3. 录制和回放的操作通常都需要有一个等待时间的设置,所以代码里加上了GUI的设置部分,GUI没有设计所以后续这块代码要优化。
  4. 考虑录制和回放倒计时需要UI提示用户并且定时触发线程执行,所以封装了一个UI更新线程的类。

按键精灵0.1版本完整代码如下:

键鼠录制的按键精灵0.1版本
  • import json
  • import threading
  • import time
  • import tkinter
  • from pynput import keyboard, mouse
  • from pynput.keyboard import Controller as KeyBoardController, KeyCode
  • from pynput.mouse import Button, Controller as MouseController
  • # 键盘动作模板
  • def keyboard_action_template():
  • return {
  • "name": "keyboard",
  • "event": "default",
  • "vk": "default"
  • }
  • # 鼠标动作模板
  • def mouse_action_template():
  • return {
  • "name": "mouse",
  • "event": "default",
  • "target": "default",
  • "action": "default",
  • "location": {
  • "x": "0",
  • "y": "0"
  • }
  • }
  • # 倒计时监听,更新UI触发自定义线程对象
  • class UIUpdateCutDownExecute(threading.Thread):
  • def __init__(self, cut_down_time, custom_thread_list):
  • super().__init__()
  • self.cut_down_time = cut_down_time
  • self.custom_thread_list = custom_thread_list
  • def run(self):
  • while self.cut_down_time > 0:
  • for custom_thread in self.custom_thread_list:
  • if custom_thread['obj_ui'] is not None:
  • custom_thread['obj_ui']['text'] = str(self.cut_down_time)
  • custom_thread['obj_ui']['state'] = 'disabled'
  • self.cut_down_time = self.cut_down_time - 1
  • time.sleep(1)
  • else:
  • for custom_thread in self.custom_thread_list:
  • if custom_thread['obj_ui'] is not None:
  • custom_thread['obj_ui']['text'] = custom_thread['final_text']
  • custom_thread['obj_ui']['state'] = 'disabled'
  • if custom_thread['obj_thread'] is not None:
  • custom_thread['obj_thread'].start()
  • time.sleep(1)
  • # 键盘动作监听
  • class KeyboardActionListener(threading.Thread):
  • def __init__(self, file_name='keyboard.action'):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'w', encoding='utf-8') as file:
  • # 键盘按下监听
  • def on_press(key):
  • template = keyboard_action_template()
  • template['event'] = 'press'
  • try:
  • template['vk'] = key.vk
  • except AttributeError:
  • template['vk'] = key.value.vk
  • finally:
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 键盘抬起监听
  • def on_release(key):
  • if key == keyboard.Key.esc:
  • # 停止监听
  • startListenerBtn['text'] = '开始录制'
  • startListenerBtn['state'] = 'normal'
  • keyboardListener.stop()
  • return False
  • template = keyboard_action_template()
  • template['event'] = 'release'
  • try:
  • template['vk'] = key.vk
  • except AttributeError:
  • template['vk'] = key.value.vk
  • finally:
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 键盘监听
  • with keyboard.Listener(on_press=on_press, on_release=on_release) as keyboardListener:
  • keyboardListener.join()
  • # 键盘动作执行
  • class KeyboardActionExecute(threading.Thread):
  • def __init__(self, file_name='keyboard.action', execute_count=0):
  • super().__init__()
  • self.file_name = file_name
  • self.execute_count = execute_count
  • def run(self):
  • while self.execute_count > 0:
  • with open(self.file_name, 'r', encoding='utf-8') as file:
  • keyboard_exec = KeyBoardController()
  • line = file.readline()
  • while line:
  • obj = json.loads(line)
  • if obj['name'] == 'keyboard':
  • if obj['event'] == 'press':
  • keyboard_exec.press(KeyCode.from_vk(obj['vk']))
  • time.sleep(0.01)
  • elif obj['event'] == 'release':
  • keyboard_exec.release(KeyCode.from_vk(obj['vk']))
  • time.sleep(0.01)
  • line = file.readline()
  • startExecuteBtn['text'] = '开始回放'
  • startExecuteBtn['state'] = 'normal'
  • self.execute_count = self.execute_count - 1
  • # 鼠标动作监听
  • class MouseActionListener(threading.Thread):
  • def __init__(self, file_name='mouse.action'):
  • super().__init__()
  • self.file_name = file_name
  • def run(self):
  • with open(self.file_name, 'w', encoding='utf-8') as file:
  • # 鼠标移动事件
  • def on_move(x, y):
  • template = mouse_action_template()
  • template['event'] = 'move'
  • template['location']['x'] = x
  • template['location']['y'] = y
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 鼠标点击事件
  • def on_click(x, y, button, pressed):
  • template = mouse_action_template()
  • template['event'] = 'click'
  • template['target'] = button.name
  • template['action'] = pressed
  • template['location']['x'] = x
  • template['location']['y'] = y
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • # 鼠标滚动事件
  • def on_scroll(x, y, x_axis, y_axis):
  • template = mouse_action_template()
  • template['event'] = 'scroll'
  • template['location']['x'] = x_axis
  • template['location']['y'] = y_axis
  • file.writelines(json.dumps(template) + "\n")
  • file.flush()
  • with mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as mouseListener:
  • mouseListener.join()
  • # 鼠标动作执行
  • class MouseActionExecute(threading.Thread):
  • def __init__(self, file_name='mouse.action', execute_count=0):
  • super().__init__()
  • self.file_name = file_name
  • self.execute_count = execute_count
  • def run(self):
  • while self.execute_count > 0:
  • with open(self.file_name, 'r', encoding='utf-8') as file:
  • mouse_exec = MouseController()
  • line = file.readline()
  • while line:
  • obj = json.loads(line)
  • if obj['name'] == 'mouse':
  • if obj['event'] == 'move':
  • mouse_exec.position = (obj['location']['x'], obj['location']['y'])
  • time.sleep(0.01)
  • elif obj['event'] == 'click':
  • if obj['action']:
  • if obj['target'] == 'left':
  • mouse_exec.press(Button.left)
  • else:
  • mouse_exec.press(Button.right)
  • else:
  • if obj['target'] == 'left':
  • mouse_exec.release(Button.left)
  • else:
  • mouse_exec.release(Button.right)
  • time.sleep(0.01)
  • elif obj['event'] == 'scroll':
  • mouse_exec.scroll(obj['location']['x'], obj['location']['y'])
  • time.sleep(0.01)
  • line = file.readline()
  • def command_adapter(action):
  • if action == 'listener':
  • if startListenerBtn['text'] == '开始录制':
  • custom_thread_list = [
  • {
  • 'obj_thread': KeyboardActionListener(),
  • 'obj_ui': startListenerBtn,
  • 'final_text': '录制中...esc停止录制'
  • },
  • {
  • 'obj_thread': MouseActionListener(),
  • 'obj_ui': None,
  • 'final_text': None
  • }
  • ]
  • UIUpdateCutDownExecute(startTime.get(), custom_thread_list).start()
  • elif action == 'execute':
  • if startExecuteBtn['text'] == '开始回放':
  • custom_thread_list = [
  • {
  • 'obj_thread': KeyboardActionExecute(execute_count=playCount.get()),
  • 'obj_ui': startExecuteBtn,
  • 'final_text': '回放中...关闭程序停止回放'
  • },
  • {
  • 'obj_thread': MouseActionExecute(execute_count=playCount.get()),
  • 'obj_ui': None,
  • 'final_text': None
  • }
  • ]
  • UIUpdateCutDownExecute(endTime.get(), custom_thread_list).start()
  • def isNumber(content):
  • if content.isdigit() or content == "":
  • return True
  • else:
  • return False
  • if __name__ == '__main__':
  • root = tkinter.Tk()
  • root.title('按键精灵-蓝士钦')
  • root.geometry('200x200+400+100')
  • listenerStartLabel = tkinter.Label(root, text='录制倒计时')
  • listenerStartLabel.place(x=10, y=10, width=80, height=20)
  • startTime = tkinter.IntVar()
  • listenerStartEdit = tkinter.Entry(root, textvariable=startTime)
  • listenerStartEdit.place(x=100, y=10, width=60, height=20)
  • startTime.set(3)
  • listenerTipLabel = tkinter.Label(root, text='秒')
  • listenerTipLabel.place(x=160, y=10, width=20, height=20)
  • startListenerBtn = tkinter.Button(root, text="开始录制", command=lambda: command_adapter('listener'))
  • startListenerBtn.place(x=10, y=45, width=180, height=30)
  • executeEndLabel = tkinter.Label(root, text='回放倒计时')
  • executeEndLabel.place(x=10, y=85, width=80, height=20)
  • endTime = tkinter.IntVar()
  • executeEndEdit = tkinter.Entry(root, textvariable=endTime)
  • executeEndEdit.place(x=100, y=85, width=60, height=20)
  • endTime.set(6)
  • executeTipLabel = tkinter.Label(root, text='秒')
  • executeTipLabel.place(x=160, y=85, width=20, height=20)
  • playCountLabel = tkinter.Label(root, text='回放次数')
  • playCountLabel.place(x=10, y=115, width=80, height=20)
  • playCount = tkinter.IntVar()
  • playCountEdit = tkinter.Entry(root, textvariable=playCount)
  • playCountEdit.place(x=100, y=115, width=60, height=20)
  • playCount.set(1)
  • playCountTipLabel = tkinter.Label(root, text='次')
  • playCountTipLabel.place(x=160, y=115, width=20, height=20)
  • startExecuteBtn = tkinter.Button(root, text="开始回放", command=lambda: command_adapter('execute'))
  • startExecuteBtn.place(x=10, y=145, width=180, height=30)
  • root.mainloop()

脚本精灵0.1版本完成?

image

还需要考虑的点:

  1. 键盘事件没有记录用户每个动作之间的延迟时间,无法准确重放用户的输入节奏,后续考虑记录时间间隔点。
  2. 鼠标事件用户移动的越快,产生的点位变化也就越频繁,所以鼠标在回放时的速度与用户的操作基本一致。
  3. 鼠标没有停止回放的快捷键,要考虑如何停止回放鼠标事件。
  4. 输入法切换可能导致重放键盘按键时输入不准确,需要录制时是什么输入状态,重放时也要对应的键盘属性和状态
  5. …还有很多需要考虑的点(原本只是想简单的做个示例程序)

程序只在MacOS平台上实验过,其他平台还未实验,一个相对完整的按键精灵在录制时应该获取更多的信息,这样在回放的时候才足够准确,后续考虑做一个更加精确的按键精灵,比如加入获取屏幕像素点,回放时通过采样比对,达到为所欲为功能。

GitHub地址:

https://github.com/lanshiqin/JerryMouse

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐