作为在特定Web界面上命中某些点的程序的一部分,此组件使用户可以单击三个点并编写一个配置文件,该文件指示该程序每次运行时将光标精确放置在何处。这些行在程序的主体中时按预期的方式工作(Python 3.6);问题是,我想将它们隔离为一个功能,以便使用户能够选择是否重新配置。 (如果用户没有切换浏览器或调整大小,则可以使用现有的配置文件。)
我希望知识渊博的Pythonista可以帮助我理解为什么仅在适当的地方以 window = Tk()开始缩进这些行,然后将其缩进四个/八个空格并将它们放在函数中会导致它们 运行正常,而不是在第一次调用on_click时挂断电话。 (编辑:来自终端的错误消息在脚本下方)
import threading, pynput, os, configparser
from pynput.mouse import Listener
from tkinter import *
configfile_name = "config.ini"
cfg = configparser.ConfigParser()
def write_config(x_coord, y_coord):
global configfile_name
c = open(configfile_name, "a", encoding="utf-8")
c.write('x=' + x_coord + '\r')
c.write('y=' + y_coord)
c.write('\r\n')
c.close()
def write_first_section(section_name):
global configfile_name
c = open(configfile_name, "w", encoding="utf-8")
c.write('[' + section_name + '] \r')
c.close()
def write_section(section_name):
global configfile_name
c = open(configfile_name, "a", encoding="utf-8")
c.write('[' + section_name + '] \r')
c.close()
def on_click(x, y, button, pressed) :
global count, window, listener
write_config(str(x), str(y))
window.after(2000, window.destroy)
listener.stop()
window = Tk()
window.title("Map your screen")
window.geometry('350x80+300+225')
window.lift()
write_first_section('tab')
lbl = Label(window, text="With the QP chat interface screen up,\nclick the 'New' tab at upper left above the blue bar")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
window.mainloop()
listener.join()
listener.stop()
write_section('pickup')
window = Tk()
window.title("Step two!")
window.geometry('350x80+300+225')
window.lift()
lbl = Label(window, text="Now, click just below the blue bar")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
window.mainloop()
listener.join()
listener.stop()
write_section('paste')
window = Tk()
window.title("Step three!")
window.geometry('350x80+300+225')
window.lift()
lbl = Label(window, text="Lastly, click in the text box")
lbl.grid(column=0, row=0)
with Listener(on_click=on_click) as listener:
window.mainloop()
Unhandled exception in listener callback
Traceback (most recent call last):
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 157, in inner
return f(self, *args, **kwargs)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/xorg.py", line 458, in _handler
self._handle(self._display_stop, event)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/mouse/_xorg.py", line 141, in _handle
self.on_click(px, py, self._button(event.detail), True)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 78, in inner
if f(*args) is False:
File "does_it_all.py", line 37, in on_click
window.after(2000, window.destroy)
NameError: name 'window' is not defined
Traceback (most recent call last):
File "does_it_all.py", line 231, in <module>
map()
File "does_it_all.py", line 192, in map
listener.join()
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 205, in join
six.reraise(exc_type, exc_value, exc_traceback)
File "/home/bruce/.local/lib/python3.6/site-packages/six.py", line 692, in reraise
raise value.with_traceback(tb)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 157, in inner
return f(self, *args, **kwargs)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/xorg.py", line 458, in _handler
self._handle(self._display_stop, event)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/mouse/_xorg.py", line 141, in _handle
self.on_click(px, py, self._button(event.detail), True)
File "/home/bruce/.local/lib/python3.6/site-packages/pynput/_util/__init__.py", line 78, in inner
if f(*args) is False:
File "does_it_all.py", line 37, in on_click
window.after(2000, window.destroy)
NameError: name 'window' is not defined
当我尝试将on_click(....)函数定义之后的所有内容放入一个称为map()的函数中,然后尝试运行map()时,在将[tab]写入config.ini文件后,它挂起了,使第一个窗口停留在屏幕上。但是,当我如上所述运行它时,它会在所有三个窗口中正常运行并写入配置文件的所有三个部分。 我确定脚本中存在严重的错误,但是:为什么为什么这32行在开放时运行良好,而在包含函数时就中断了呢? 感谢您的帮助和建设性的指责!
答案 0 :(得分:0)
将这些行移动到函数中时,您定义的window
(和listener
)变量不再是全局变量,而成为该函数的局部变量。您的on_click
函数依赖于window
(和listener
)进行全局定义,并且由于它们不再作为全局变量存在,因此您的代码中断了。
最小的解决方法是添加:
global window, listener
位于新函数的顶部,因此它将window
和listener
视为全局变量,而不是将它们视为局部变量的默认行为。
一种更彻底的解决方案是编写一个类,其中window
和listener
(可能还有其他)是实例属性,可以通过self
使用新函数和{{ 1}}是该类的方法。在这种情况下并不重要,但是只要您发现自己依赖on_click
来实现可变的全局状态,通常这是一个糟糕的设计,并且您确实真的想要一个类。