尝试创建鼠标记录器,但它不断循环吗?

时间:2019-06-02 19:19:58

标签: python multithreading python-multithreading pynput

我正在Pynput上做手,我首先创建一个简单的程序来记录鼠标的运动,然后在单击按钮时重播这些运动。

但是,每当我单击鼠标时,它就会开始变得怪异并不断循环。我认为它正在以超高的速度运行,但是我最终不得不使用Alt-F4外壳来停止它。

任何帮助将不胜感激。

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()

2 个答案:

答案 0 :(得分:1)

您陷入了无限循环。我认为您在on_click方法中引用的侦听器可能为null或未定义。另外,根据一些文档,我发现您需要为on_click方法返回false才能停止监听

这就是我正在查看的内容:

https://pythonhosted.org/pynput/mouse.html

答案 1 :(得分:1)

使用多个线程时必须小心(这里就是这种情况,因为listener.stop()在其自己的线程中运行)。显然,只要您在回调函数中,即使调用了on_move,所有事件仍将得到处理。因此,在回放时,对于您设置的每个鼠标位置,都会调用positions回调函数,以便再次将鼠标位置添加到列表中,这将导致无限循环。

通常,在回调函数中实现太多功能(在本例中为“重播”)是一种不好的做法。更好的解决方案是使用一个事件向另一个线程发出信号,表明已单击鼠标按钮。请参见以下示例代码。几点说明:

  • 我添加了一些打印语句以查看发生的情况。
  • 我在鼠标位置之间添加了一个小的延迟,以真正查看播放效果。 (注意:如果挂起,这也可能使退出该应用程序更容易!)
  • 我更改了一些变量名称以使其更有意义。将数组称为“ arr”不是一个好主意。尝试使用真正描述变量的名称。在这种情况下,这是一个职位列表,因此我选择将其称为return False
  • 我正在使用pynput.mouse.Listener.stop来停止鼠标控制器。 documentation声明“从任何地方调用StopException,提高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) 以停止侦听器。”但就我个人而言,我认为返回False是最干净的最安全的解决方案。
{{1}}

请注意,当您在Windows命令提示符下运行此命令时,该应用程序可能会挂起,因为您已经按下了鼠标按钮,然后开始发送鼠标位置。这将导致“拖动”运动,从而使终端暂停。如果发生这种情况,您只需按Escape键,程序将继续运行。