pyautogui mouseDown() 不适用于自动鼠标移动

问题描述

在Automate the Boring Things的第20章中,有一个使用pyautogui绘制螺旋线的例子。代码使用 .drag() 绘制每个线段,但在每个角上鼠标释放光标并开始新的一行。这会为您使用的任何画笔类型在每个角落创建一个中断。

enter image description here

为了解决这个美学问题,我尝试修改代码以使用 .mouseDown().move()。然而,这最终除了从左上角到左下角的一条线之外什么也没画,就好像 while 循环的每次迭代都在重复单击。

通过测试:

while True:
    pyautogui.mouseDown()

在 mspaint 中,.mousedown() 函数确实在我自己移动鼠标时正确执行。

尝试:

while True:
    pyautogui.mouseDown()
    pyautogui.move(300,duration=0.5)

也正确地绘制了一条线,但以 300 像素块为单位进行绘制。 IE。每次循环迭代时,线段都会加载到 mspaint 上。

在正方形中重复这个实验:

while True:
    pyautogui.mouseDown()
    pyautogui.move(300,duration=0.5)
    pyautogui.move(0,300,duration=0.5)
    pyautogui.move(-300,-300,duration=0.5)

最后什么都没画。

这里发生了什么?为什么 .mouseDown() 的行为如此不一致?如何让我的代码绘制一个漂亮的不间断螺旋?

完整的原始代码供参考:

#! python3
# spiralDraw.py - draws a spiral in mspaint

import pyautogui
import time

time.sleep(5)   # give time to go to paint app
distance = 300
change = 20
pyautogui.mouseDown()

while distance > 0:
    pyautogui.move(distance,duration=0.5)   
    distance = distance - change
    pyautogui.move(0,distance,duration=0.5)   
    pyautogui.move(-distance,duration=0.5)  
    distance = distance - change
    pyautogui.move(0,-distance,duration=0.5)
    
if distance == 0:
    pyautogui.mouseUp()

解决方法

我发现你必须使用 drag 来画一条线,因为 move 函数只移动指针而不点击 (documentation)。

但是,您仍然可以使用 mouseDown 函数代替 click 函数,因为它“与鼠标左键单击的作用相同”({{ 3}}).

drag 函数(至少在包的最新版本中)需要一个名为 button 的参数,它可以是 "left""right""middle"代表鼠标点击三下 (documentation) 中的每一次。

根据前面的信息,代码为:

import pyautogui
import time

time.sleep(5)  # give time to go to paint app
distance = 300
change = 20
pyautogui.mouseDown()

while distance > 0:
    pyautogui.drag(distance,duration=0.5,button='left')
    distance = distance - change
    pyautogui.drag(0,distance,button='left')
    pyautogui.drag(-distance,-distance,button='left')

if distance < 0:
    pyautogui.mouseUp()
,

虽然我不确定为什么会这样,但可以通过将鼠标保持和鼠标移动分成单独的线程并同时运行它们来实现预期的结果。

这是使用蜡笔画笔的非多线程代码的输出,注意拖动实现的块状角,因为每一行都是单独的鼠标按下:

enter image description here

这是将任务分成两个线程并同时运行它们的代码的结果,你可以看到角落是平滑的,并且当我按下 ctrl+z 整个绘图时,它都是一条长线消失:

enter image description here

这里是简单实现多线程的代码:

import pyautogui
import time
import threading

def mouseHoldDown():
    global distance
    while distance > 0:
        pyautogui.mouseDown()
    if distance == 0:
        time.sleep(1)
        pyautogui.mouseUp()
    
def movingSpiralMouse():
    global distance
    change = 20
    while distance > 0:
        pyautogui.move(distance,duration=0.25)
        distance = distance - change
        pyautogui.move(0,duration=0.25)
        pyautogui.move(-distance,duration=0.25)

distance = 300
time.sleep(5)

mouseObj = threading.Thread(target=mouseHoldDown)
mouseObj.start()

moveObj = threading.Thread(target=movingSpiralMouse)
moveObj.start()

我仍然非常感谢您解释为什么需要将其分成多个线程才能达到预期的结果。