Python使用Pynput实现scrcpy多按键映射下同步鼠标按下事件方案
问题根源
你当前代码无法实现多点操作的核心原因是:你通过pynput模拟的是电脑端单鼠标的左键点击,普通鼠标硬件本身就不支持同时在多个不同位置触发点击,自然无法对应安卓端的多点触控需求。
实现方案
完全可以用Python实现该需求,你需要放弃模拟电脑鼠标的思路,改为直接通过adb向安卓设备发送独立的多点触控事件,每个映射按键对应一个独立的触控点ID,不同按键的操作互不干扰。
具体修改步骤
- 确保你的电脑已经通过adb连接了安卓设备(使用scrcpy时默认已经完成adb连接,无需额外操作)
- 将原有的模拟鼠标点击逻辑替换为调用adb命令发送触控事件,每个功能按键分配唯一的触点ID,例如:
- WASD移动对应触点ID 0
- 空格键跳跃对应触点ID 1
- 其他功能键依次分配ID 2、3、4...
- 按键按下时发送对应触点的
DOWN事件,按键松开时发送对应触点的UP事件,互不影响。
修改后代码示例
import subprocess from pynput.keyboard import Key, KeyCode, Listener # 配置参数 CENTER = 315 HEIGHT = 800 LISTEN = None # 每个按键对应唯一的触控点ID,避免冲突 POINTER_ID_MAP = { 'w': 0, 's': 0, 'a': 0, 'd': 0, 'space': 1, 'c': 2, 'r': 3, 'f': 4, 'shift_l': 5, 'q': 6, '1': 7, '2': 8, '3': 9 } def adb_touch_down(pointer_id, x, y): """发送指定触点的按下事件""" subprocess.run( ['adb', 'shell', 'input', 'motionevent', f'DOWN/{pointer_id}', str(x), str(y)], capture_output=True ) def adb_touch_up(pointer_id, x, y): """发送指定触点的抬起事件""" subprocess.run( ['adb', 'shell', 'input', 'motionevent', f'UP/{pointer_id}', str(x), str(y)], capture_output=True ) def adb_touch_move(pointer_id, x, y): """发送指定触点的移动事件""" subprocess.run( ['adb', 'shell', 'input', 'motionevent', f'MOVE/{pointer_id}', str(x), str(y)], capture_output=True ) # 功能函数 def w(): adb_touch_move(POINTER_ID_MAP['w'], CENTER, HEIGHT - 100) def s(): adb_touch_move(POINTER_ID_MAP['s'], CENTER, HEIGHT + 100) def a(): adb_touch_move(POINTER_ID_MAP['a'], CENTER - 100, HEIGHT) def d(): adb_touch_move(POINTER_ID_MAP['d'], CENTER + 100, HEIGHT) def space(): adb_touch_down(POINTER_ID_MAP['space'], int(CENTER*5.75), int(HEIGHT*0.95)) def c(): adb_touch_down(POINTER_ID_MAP['c'], int(CENTER*5.15), int(HEIGHT*1.2)) def r(): adb_touch_down(POINTER_ID_MAP['r'], int(CENTER*4.75), int(HEIGHT*1.15)) def f(): adb_touch_down(POINTER_ID_MAP['f'], int(CENTER*0.5), int(HEIGHT*0.7)) def ctrl(): adb_touch_down(POINTER_ID_MAP['shift_l'], int(CENTER*5.15), HEIGHT) def q(): adb_touch_down(POINTER_ID_MAP['q'], int(CENTER*5.3), int(HEIGHT*0.77)) def switch1(): adb_touch_down(POINTER_ID_MAP['1'], int(CENTER*2.75), int(HEIGHT*1.15)) def switch2(): adb_touch_down(POINTER_ID_MAP['2'], int(CENTER*3.3), int(HEIGHT*1.15)) def switch3(): adb_touch_down(POINTER_ID_MAP['3'], int(CENTER*3), int(HEIGHT*1.05)) # 按下移动键时先按下移动触点 move_pressed = False def on_press(key): global move_pressed try: if key == KeyCode(char='w'): if not move_pressed: adb_touch_down(POINTER_ID_MAP['w'], CENTER, HEIGHT) move_pressed = True w() elif key == KeyCode(char='s'): if not move_pressed: adb_touch_down(POINTER_ID_MAP['s'], CENTER, HEIGHT) move_pressed = True s() elif key == KeyCode(char='a'): if not move_pressed: adb_touch_down(POINTER_ID_MAP['a'], CENTER, HEIGHT) move_pressed = True a() elif key == KeyCode(char='d'): if not move_pressed: adb_touch_down(POINTER_ID_MAP['d'], CENTER, HEIGHT) move_pressed = True d() elif key == Key.space: space() elif key == KeyCode(char='c'): c() elif key == KeyCode(char='r'): r() elif key == KeyCode(char='f'): f() elif key == Key.shift_l: ctrl() elif key == KeyCode(char='q'): q() elif key == KeyCode(char='1'): switch1() elif key == KeyCode(char='2'): switch2() elif key == KeyCode(char='3'): switch3() elif key == Key.tab: LISTEN.stop() except AttributeError: pass def on_release(key): global move_pressed try: # 处理移动键释放 if key in [KeyCode(char='w'), KeyCode(char='s'), KeyCode(char='a'), KeyCode(char='d')]: adb_touch_up(POINTER_ID_MAP['w'], CENTER, HEIGHT) move_pressed = False # 处理其他按键释放 elif key == Key.space: adb_touch_up(POINTER_ID_MAP['space'], int(CENTER*5.75), int(HEIGHT*0.95)) elif key == KeyCode(char='c'): adb_touch_up(POINTER_ID_MAP['c'], int(CENTER*5.15), int(HEIGHT*1.2)) elif key == KeyCode(char='r'): adb_touch_up(POINTER_ID_MAP['r'], int(CENTER*4.75), int(HEIGHT*1.15)) elif key == KeyCode(char='f'): adb_touch_up(POINTER_ID_MAP['f'], int(CENTER*0.5), int(HEIGHT*0.7)) elif key == Key.shift_l: adb_touch_up(POINTER_ID_MAP['shift_l'], int(CENTER*5.15), HEIGHT) elif key == KeyCode(char='q'): adb_touch_up(POINTER_ID_MAP['q'], int(CENTER*5.3), int(HEIGHT*0.77)) elif key == KeyCode(char='1'): adb_touch_up(POINTER_ID_MAP['1'], int(CENTER*2.75), int(HEIGHT*1.15)) elif key == KeyCode(char='2'): adb_touch_up(POINTER_ID_MAP['2'], int(CENTER*3.3), int(HEIGHT*1.15)) elif key == KeyCode(char='3'): adb_touch_up(POINTER_ID_MAP['3'], int(CENTER*3), int(HEIGHT*1.05)) except AttributeError: pass # 启动监听 with Listener(on_press=on_press, on_release=on_release) as LISTEN: LISTEN.join()
优化建议
如果觉得adb命令调用延迟较高,可以改用Python的adb-shell库直接通过socket发送adb指令,减少进程调用开销。
内容的提问来源于stack exchange,提问作者OmbyMasiaka
相关产品推荐
相关产品推荐

