.Persona. 发表于 2020-12-22 13:48:13

对于pyautogui的鼠标坐标打印脚本的疑问

大佬们,是这样,我买了一本教程,书名:《Python编程快速上手》并根据其第18章按照要求抄写下了如下代码,但是发现鼠标坐标并不能显示出来。

我不理解是我对作者的讲解出了误解,还是版本不兼容这种写法。

请大家帮我看一看。

import pyautogui
print('Press ctrl+C to quit.')
try:
    while True:
      x,y = pyautogui.position()
      positionStr = 'X:' + str(x).rjust(4) + 'Y:' + str(y).rjust(4)
      # 我曾尝试在这里写入最后的两行代码,但可能是因为没有设置时间,坐标打印出来以后转瞬即逝。
except KeyboardInterrupt:
    print('\nDone.')
print(positionStr, end='')
print('\b' * len(positionStr), end='', flush=True)

万分感谢。

jackz007 发表于 2020-12-22 14:32:45

本帖最后由 jackz007 于 2020-12-22 14:39 编辑

      这个代码必须在按下 Ctrl-C 的时候,才会显示出 X、Y 的坐标值,如果是用从资源管理器中用鼠标双击源代码文件的方式运行,那么,在打印坐标的代码之后,再添加一个 input(),才能保证 CMD 窗口不会一闪即逝。
import pyautogui
print('Press ctrl+C to quit.')
try:
    while True:
      x,y = pyautogui.position()
      positionStr = 'X:' + str(x).rjust(4) + 'Y:' + str(y).rjust(4)
      # 我曾尝试在这里写入最后的两行代码,但可能是因为没有设置时间,坐标打印出来以后转瞬即逝。
except KeyboardInterrupt:
    print('\nDone.')
print(positionStr, end='')
print('\b' * len(positionStr), end='', flush=True)
input()                              # 添加此句
      不信的话,多运行几次,按下 Ctrl - C 前,挪动一下鼠标,你会发现,每一次的坐标值都会不一样。

.Persona. 发表于 2020-12-22 14:48:33

jackz007 发表于 2020-12-22 14:32
这个代码必须在按下 Ctrl-C 的时候,才会显示出 X、Y 的坐标值,如果是用从资源管理器中用鼠标双击 ...

你好,是这样的,这本书的作者描述这个程序的时候,表示画面会实时如下显示(即x和y会一直显示,并随着鼠标的移动实时改变):
Press ctrl+c to quit.
X:    290 Y:    424    # 假设鼠标此时停在这里
并且按下ctrl+c捕捉异常就可以退出这个程序。
实际上,确实按照你说的,按照我那样的抄写只有按下ctrl+c以后才能显示坐标,可这显然不是作者本意。

我尝试把input()写入cmd后被报错,提示positionStr未定义,有些令人疑惑。

jackz007 发表于 2020-12-22 15:35:06

本帖最后由 jackz007 于 2020-12-22 15:38 编辑

.Persona. 发表于 2020-12-22 14:48
你好,是这样的,这本书的作者描述这个程序的时候,表示画面会实时如下显示(即x和y会一直显示,并随着鼠 ...

       明白你的意图了,代码缩进的问题,显示坐标的语句被写在了循环外面,现在再测
import pyautogui
print('Press ctrl+C to quit.')
try:
    x0 , y0 = pyautogui.position()
    positionStr = 'X:' + str(x0).rjust(4) + '\tY:' + str(y0).rjust(4)
    while True:
      x , y = pyautogui.position()
      if x != x0 or y != y0:
            print('\b' * (len(positionStr) + 1) , end = '', flush = True)
            positionStr = 'X:' + str(x).rjust(4) + '\tY:' + str(y).rjust(4)
            print(positionStr , end = '')
            x0 , y0 = x , y
except KeyboardInterrupt:
    print('\nDone.')

hrp 发表于 2020-12-22 15:35:27

曾经回答过一个类似的问题,给你参考下
不仅能在控制台显示鼠标坐标,也可以在鼠标旁边跟随一个显示坐标的输入框
import tkinter as tk
from threading import Thread
from time import sleep

import pyautogui as ag


KEEP_LISTEN = True
THREAD_LISTENING = None
POSITION = 0, 0
# 刷新时间间隔(毫秒)
TIME_INTERVAL = 10


def listening():
    '''监听函数'''
    global POSITION, KEEP_LISTEN
    KEEP_LISTEN = True
    while KEEP_LISTEN:
      new_position = ag.position()
      if new_position != POSITION:
            POSITION = new_position
            print(POSITION)
      sleep(TIME_INTERVAL / 1000)


def start_listen():
    '''调用此函数开始监听'''
    global THREAD_LISTENING
    if THREAD_LISTENING:
      return
    THREAD_LISTENING = Thread(target=listening)
    THREAD_LISTENING.start()


def stop_listen():
    '''调用此函数停止监听'''
    global KEEP_LISTEN, THREAD_LISTENING
    KEEP_LISTEN = False
    THREAD_LISTENING.join()
    THREAD_LISTENING = None


root = tk.Tk()
root.attributes("-alpha", 0.6)
root.overrideredirect(True)

etyText = tk.StringVar()


def mouse_move_event():
    # POSITION + 20 原因是使输入框离鼠标远点防止影响鼠标点击,实际使用可以改回来
    root.geometry(f'80x20+{POSITION + 20}+{POSITION}')
    etyText.set(f'{POSITION},{POSITION}')
    root.after(TIME_INTERVAL, mouse_move_event)


ety = tk.Entry(root, textvariable=etyText)
ety.pack()

start_listen()
root.after(TIME_INTERVAL, mouse_move_event)

tk.mainloop()

qiaoqiaoqq 发表于 2020-12-22 15:58:16

6666666666

.Persona. 发表于 2020-12-22 16:02:58

jackz007 发表于 2020-12-22 15:35
明白你的意图了,代码缩进的问题,显示坐标的语句被写在了循环外面,现在再测

感谢大佬,这很好地解决了问题,鉴于你是第一个帮助我解决问题的人,所以我想设你为最佳。

.Persona. 发表于 2020-12-22 16:04:37

hrp 发表于 2020-12-22 15:35
曾经回答过一个类似的问题,给你参考下
不仅能在控制台显示鼠标坐标,也可以在鼠标旁边跟随一个显示坐标的 ...

这位大佬答案也很好,只不过我还没有学这么多,先复制了下来,跑了一下,发现非常方便。

首先感谢大佬的分享,等我深入学习后再好好研究一下写法。

.Persona. 发表于 2020-12-23 09:04:02

jackz007 发表于 2020-12-22 15:35
明白你的意图了,代码缩进的问题,显示坐标的语句被写在了循环外面,现在再测

感谢大佬昨天的帮助,我想了想,其实是我误会作者了。。

是我自己对书的理解出了问题,其实正确代码确实是应该在我原答案注释处写入最后的两行,即:
import pyautogui
try:
    while True:
      x,y = pyautogui.position()
      positionStr = 'X:' + str(x).rjust(4) + 'Y:' + str(y).rjust(4)
      print(positionStr, end='')
      print('\b' * len(positionStr), end='', flush=True)
except KeyboardInterrupt:
    print('\nDone.')
原答案问题在于把这两条写在了循环外,循环内一直在赋值又跳不出循环,导致无法执行下面的打印,所以就看不到了。
实际上,我当时那样注释,是因为我在pycharm有尝试过本答案的代码,但是发现显示异常,所以我才觉得有问题,没想到回过头来原来一开始就是对的,只是要在cmd环境下运行而已。。。
大佬的答案我也详细研究过:
是先将开始程序时鼠标所在位置赋值给(x0,y0)
后面鼠标发生移动则触发if语句,首先打印(x0,y0)
再将positionStr更新为(x,y),打印(x,y)
最后将xy赋给x0y0来跳出if使以后鼠标移动的坐标重新赋值给xy,来重复这个过程来实现坐标实时更新。
这个想法很好,在不大幅改变原答案程序的前提下当时很好的解决了我的问题,十分感谢。
就是按照本答案给大佬提一个小建议:
为什么不考虑把开始程序时鼠标的初始坐标也加入到x和y的打印中去呢?可以试着把x0y0去掉,让x和y去处理所有的坐标打印,这样可读性似乎更高一些。
最后,还是感谢大佬当时解决了我的问题~
页: [1]
查看完整版本: 对于pyautogui的鼠标坐标打印脚本的疑问