【发布时间】:2021-07-17 06:06:59
【问题描述】:
无法将 1 次鼠标单击转换为多次鼠标单击。基本上我想做的是一次控制多个窗口。我想点击一个主窗口并将点击传播到后续窗口。在这个 sn-p 中有 4 个窗口,我通过确定它和主窗口之间的 offset 来跟踪它们。
我将 python3 与 pynput 用于鼠标侦听器和 pyautogui 用于鼠标控制。
我遇到的问题是设置鼠标侦听器,使其侦听我的实际点击,但忽略编程点击。现在,我认为它陷入了一个无限循环,我的初始点击触发on_click 事件,传播点击,每个触发一个额外的on_click 事件,传播点击等。当我运行下面的代码时它开始很好,然后当我第一次点击它时,我的鼠标会严重滞后一分钟,然后恢复正常,不再有鼠标监听器处于活动状态。我的猜测是故障保护功能会启动以使其恢复正常。
我尝试过的事情:
- 使用 pynput 进行侦听和控制 - 这不会改变结果
- 在传播的点击完成后停止侦听器并创建一个新的侦听器 - 仍然没有改变结果的糟糕的 hacky 解决方案
- 信号量锁定,
_value在已获取信号量的情况下偷看忽略事件 - 也是 hacky 并且不起作用 - 通过线程调用
propagateActions并等待完成,然后从on_click事件返回 - 不起作用 - 注释掉
pyautogui.click()- 这允许预期行为将鼠标移动到后续位置并在之后将其返回到其初始位置。无需点击,它就可以完美运行。随着点击,它会滞后并且听众死亡。 - 搜索 stackoverflow - this question 在结果方面有相似之处,但没有得到答复,并试图实现不同的目标。
我的 sn-p 如下:
from pynput import mouse, keyboard
import pyautogui
pyautogui.PAUSE = 0.01
mouseListener = None
killSwitch = False
# this is just a keyboard listener for a kill switch
def on_release(key):
if key == keyboard.Key.f1:
global killSwitch
print('@@@ Kill switch activated @@@')
killSwitch = True
# on mouse release I want to propogate a click to 4 other areas
def on_click(x, y, button, pressed):
print('{0} at {1}'.format('Pressed' if pressed else 'Released', (x, y)))
if not pressed:
propogateActions(x, y, button)
# propogates clicks
def propogateActions(x, y, button):
print('propogating actions to {0} windows'.format(len(offsets)+1))
for offset in offsets:
pyautogui.moveTo(x+offset.x, y+offset.y)
print('mouse moved')
if button == mouse.Button.left:
print('left clicking at ({0}, {1})'.format(x+offset.x, y+offset.y))
pyautogui.click()
pyautogui.moveTo(x, y)
# point class for ease of use
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Point(x={0}, y={1})'.format(self.x, self.y)
# main method
def doTheThing():
print('started')
while not killSwitch:
pass
# initializations and starting listeners
# offsets tracks how far the subsequent clicks are from the initial click point
offsets = [Point(50, 0), Point(50, 50), Point(0, 50)]
keyboardListener = keyboard.Listener(on_release=on_release)
mouseListener = mouse.Listener(on_click=on_click)
keyboardListener.start()
mouseListener.start()
doTheThing()
我的问题:
- 有什么方法可以只监听“真实”点击而不是程序化点击?
- 如果不是,我可以暂停鼠标侦听器,然后在传播的点击发生后以某种方式重新启动它吗?
这是与当前问题相关的一小部分代码。 offsets 有一个更合适的初始化设置,还有其他花里胡哨,但这是与问题相关的部分。感谢您的帮助。
【问题讨论】:
-
对于系统来说,所有这些点击都是真实的。
-
如果您在一个窗口中单击,那么也许您应该仅在单击某个区域时检查鼠标位置和移动。
-
您还可以测量点击之间的时间,并在另一次点击后几毫秒跳过点击。
-
是的,我更想问的是用户点击和程序化点击之间是否存在不同之处。从我的程序来看,情况并非如此。对于您的其他 2 个 cmets,这些可以工作,但会限制解决方案。主窗口只能位于固定位置,时间会限制我执行操作的速度。两种脆弱的解决方案,但可以工作。我最终找到了正确的解决方案。在下面回答。
标签: python python-3.x mouselistener pyautogui pynput