【问题标题】:How do event listeners work in Python's Turtle Module? And why are they non-blocking even though they are constantly listening in the background?事件监听器如何在 Python 的 Turtle 模块中工作?为什么即使他们一直在后台收听,他们也不会阻塞?
【发布时间】:2021-10-03 13:49:11
【问题描述】:

在这段代码中,我使用 Turtle Module for Python 创建了一个程序,我听说它是​​用 Tkinter 构建的。这个工作代码会让乌龟说“啊!”当你点击它时,然后传送。最让我困惑的是 t.onclick() 方法。它如何在允许其余代码运行的同时继续监听海龟的点击,这与 input() 函数不同,它在继续之前等待用户输入输入?

另外,事件处理程序在 Python 中是如何工作的?它是否会通过某种永远循环不断检查背景中的点击?是否有一种机制允许它保持空闲并在收到点击时以某种方式激活?还是有其他东西完全可以让它以它的方式工作?

from turtle import *
from time import sleep
from random import randint

t = Turtle()
t.color("red")
t.penup()
t.shape("turtle")
t.speed(100)
t.points = 0

w = 200
h = 150

def rand_move():
    t.goto(randint(-w, w), randint(-h, h))

def catch(x, y):
    t.write("Ah!", font=("Arial", 14, "normal"))
    t.points = t.points + 1
    rand_move()

t.onclick(catch)

while t.points < 3:
    sleep(1.5)
    rand_move()

t.write("WOW! You're good at catching me!", font=('Arial', 16, 'bold'))
t.hideturtle()

我曾尝试查找 Turtle 源代码,但未能破译它,甚至在 Google 上搜索了相当多的网站,但似乎没有一个对这个问题足够具体。任何帮助解决这个问题将不胜感激!

【问题讨论】:

    标签: python event-handling python-turtle


    【解决方案1】:

    input() 函数是 Python 内置函数,不是tkinter 的一部分。后者有自己的mainloop(),它通常处理所有用户输入——除非它的处理被某些函数(例如input()或任何长时间运行的函数)干扰。发生这种情况时,GUI 将“冻结”。

    【讨论】:

    • 感谢您的进一步澄清,但是经过更多阅读,我仍然不太明白为什么我能够在我的 t.onclick() 行之后添加更多代码,因为 mainloop() 已说明被阻止。
    • tkinter 支持bind() 多种不同类型的用户输入Events 到用户定义的“事件处理程序”函数。见Events: responding to stimuli。完成此操作的低级细节主要由包装的 Tcl/Tk GUI 工具包在内部处理(我相信它可以在它支持的各种平台上执行所需的任何操作)。
    【解决方案2】:

    我认为难以理解海龟事件如何工作的部分原因是这段代码不属于事件驱动的海龟程序:

    while t.points < 3:
        sleep(1.5)
        rand_move()
    

    相反,我们应该将控制权移交给mainloop(),或者显式地,或者在某些编程环境中,隐式地。让我们将您的代码重写为事件驱动的海龟程序:

    from turtle import Screen, Turtle
    from random import randint
    
    WIDTH, HEIGHT = 640, 480
    CURSOR_SIZE = 20
    
    def rand_move():
        turtle.goto(randint(CURSOR_SIZE - WIDTH//2, WIDTH//2 - CURSOR_SIZE), randint(CURSOR_SIZE - HEIGHT//2, HEIGHT//2 - CURSOR_SIZE))
    
        if turtle.points < 3:
            screen.ontimer(rand_move, 1000)  # delay in milliseconds
        else:
            turtle.home()
            turtle.write("WOW! You're good at catching me!", align='center', font=('Arial', 16, 'bold'))
            turtle.hideturtle()
    
    def catch(x, y):
        turtle.write("Ah!", font=('Arial', 14, 'normal'))
        turtle.points += 1
    
    screen = Screen()
    screen.setup(WIDTH, HEIGHT)
    
    turtle = Turtle()
    turtle.shape('turtle')
    turtle.color('red')
    turtle.speed('fastest')
    turtle.penup()
    turtle.onclick(catch)
    
    turtle.points = 0  # user defined property
    
    rand_move()
    
    screen.mainloop()
    

    事件处理程序如何在 Python 中工作?它是否经常检查 在后台点击某种永远循环?有没有 允许它保持空闲并以某种方式激活的机制 收到点击?

    这种描述并不遥远。 Turtle 事件从 mainloop() 触发,它等待事件触发,例如鼠标点击、键盘输入、窗口关闭、计时器事件等。有关 mainloop() 在 turtle 程序中的更多信息,请参阅 this answer

    onclick() 方法只注册主循环的代码,以便在特定于海龟的点击进入时调用。就像 ontimer 注册主循环的代码,以便在将来的某个时间调用。当我们将while ...: sleep() 循环与turtle 的主循环混合使用时,我们可能会在睡眠周期中丢失事件。

    【讨论】:

      猜你喜欢
      • 2018-05-26
      • 2016-02-06
      • 2021-10-15
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多