尝试创建一个鼠标记录器,但它一直在无限循环?
Trying to create a mouse recorder, but it keeps looping endlessly?
我正在尝试使用 Pynput,我开始创建一个简单的程序来记录鼠标的移动,然后在单击按钮后重播这些移动。
但是,每次我单击鼠标时,它都会开始崩溃并无限循环。我认为它正在以超高速进行运动,但我最终不得不按 Alt-F4 shell 来停止它。
如有任何帮助,我们将不胜感激。
import pynput
arr = []
from pynput import mouse
mou = pynput.mouse.Controller()
def on_move(x,y):
Pos = mou.position
arr.append(Pos)
def on_click(x, y, button, pressed):
listener.stop()
for i in arr:
mou.position = i
print("Done")
listener = mouse.Listener(on_move = on_move, on_click=on_click)
listener.start()
你陷入了无限循环。我认为您在 on_click 方法中引用的侦听器可能为 null 或未定义。另外根据一些文档,我发现你需要 return false 才能让 on_click 方法停止监听
这就是我在看的内容:
使用多线程时必须小心(这里就是这种情况,因为 mouse.Listener
运行 在它自己的线程中)。显然,只要您在回调函数中,所有事件仍会被处理,即使在您调用 listener.stop()
之后也是如此。所以在回放的时候,对于你设置的每一个鼠标位置,都会调用on_move
回调函数,这样鼠标位置又会被添加到你的列表中,从而导致死循环。
一般来说,在回调函数中实现过多的功能(在本例中为 "replaying")是不好的做法。更好的解决方案是使用事件向另一个线程发出鼠标按钮已被单击的信号。请参阅以下示例代码。几点说明:
- 我添加了一些打印语句以查看发生了什么。
- 我在鼠标位置之间添加了一个小的延迟以真正看到回放。 (注意:如果应用程序挂起,这也可能使中断应用程序更容易一些!)
- 我更改了一些变量名以使其更有意义。调用数组 "arr" 不是一个好主意。尝试使用真正描述变量的名称。在本例中,它是一个位置列表,因此我选择将其命名为
positions
.
- 我正在使用
return False
来停止鼠标控制器。 documentation 声明 "Call pynput.mouse.Listener.stop
from anywhere, raise StopException
or return False
from a callback to stop the listener.",但我个人认为返回 False 是最干净、最安全的解决方案。
import threading
import time
import pynput
positions = []
clicked = threading.Event()
controller = pynput.mouse.Controller()
def on_move(x, y):
print(f'on_move({x}, {y})')
positions.append((x, y))
def on_click(x, y, button, pressed):
print(f'on_move({x}, {y}, {button}, {pressed})')
# Tell the main thread that the mouse is clicked
clicked.set()
return False
listener = pynput.mouse.Listener(on_move=on_move, on_click=on_click)
listener.start()
try:
listener.wait()
# Wait for the signal from the listener thread
clicked.wait()
finally:
listener.stop()
print('*REPLAYING*')
for position in positions:
controller.position = position
time.sleep(0.01)
请注意,当您在 Windows 命令提示符中 运行 执行此操作时,应用程序可能会挂起,因为您按下了鼠标按钮,然后开始发送鼠标位置。这会导致 "drag" 移动,从而暂停终端。如果发生这种情况,您只需按 Escape,程序将继续 运行.
我正在尝试使用 Pynput,我开始创建一个简单的程序来记录鼠标的移动,然后在单击按钮后重播这些移动。
但是,每次我单击鼠标时,它都会开始崩溃并无限循环。我认为它正在以超高速进行运动,但我最终不得不按 Alt-F4 shell 来停止它。
如有任何帮助,我们将不胜感激。
import pynput
arr = []
from pynput import mouse
mou = pynput.mouse.Controller()
def on_move(x,y):
Pos = mou.position
arr.append(Pos)
def on_click(x, y, button, pressed):
listener.stop()
for i in arr:
mou.position = i
print("Done")
listener = mouse.Listener(on_move = on_move, on_click=on_click)
listener.start()
你陷入了无限循环。我认为您在 on_click 方法中引用的侦听器可能为 null 或未定义。另外根据一些文档,我发现你需要 return false 才能让 on_click 方法停止监听
这就是我在看的内容:
使用多线程时必须小心(这里就是这种情况,因为 mouse.Listener
运行 在它自己的线程中)。显然,只要您在回调函数中,所有事件仍会被处理,即使在您调用 listener.stop()
之后也是如此。所以在回放的时候,对于你设置的每一个鼠标位置,都会调用on_move
回调函数,这样鼠标位置又会被添加到你的列表中,从而导致死循环。
一般来说,在回调函数中实现过多的功能(在本例中为 "replaying")是不好的做法。更好的解决方案是使用事件向另一个线程发出鼠标按钮已被单击的信号。请参阅以下示例代码。几点说明:
- 我添加了一些打印语句以查看发生了什么。
- 我在鼠标位置之间添加了一个小的延迟以真正看到回放。 (注意:如果应用程序挂起,这也可能使中断应用程序更容易一些!)
- 我更改了一些变量名以使其更有意义。调用数组 "arr" 不是一个好主意。尝试使用真正描述变量的名称。在本例中,它是一个位置列表,因此我选择将其命名为
positions
. - 我正在使用
return False
来停止鼠标控制器。 documentation 声明 "Callpynput.mouse.Listener.stop
from anywhere, raiseStopException
or returnFalse
from a callback to stop the listener.",但我个人认为返回 False 是最干净、最安全的解决方案。
import threading
import time
import pynput
positions = []
clicked = threading.Event()
controller = pynput.mouse.Controller()
def on_move(x, y):
print(f'on_move({x}, {y})')
positions.append((x, y))
def on_click(x, y, button, pressed):
print(f'on_move({x}, {y}, {button}, {pressed})')
# Tell the main thread that the mouse is clicked
clicked.set()
return False
listener = pynput.mouse.Listener(on_move=on_move, on_click=on_click)
listener.start()
try:
listener.wait()
# Wait for the signal from the listener thread
clicked.wait()
finally:
listener.stop()
print('*REPLAYING*')
for position in positions:
controller.position = position
time.sleep(0.01)
请注意,当您在 Windows 命令提示符中 运行 执行此操作时,应用程序可能会挂起,因为您按下了鼠标按钮,然后开始发送鼠标位置。这会导致 "drag" 移动,从而暂停终端。如果发生这种情况,您只需按 Escape,程序将继续 运行.