【问题标题】:Turtle Graphics Python, .mainloop()海龟图形 Python, .mainloop()
【发布时间】:2016-09-10 18:22:56
【问题描述】:

我正在使用 Python 进行编程,我有几个问题在任何地方都找不到答案(请阅读所有问题,因为它们是我上一个问题的基础):

1..mainloop() 到底是做什么的?我阅读了 Stack Overflow 中的所有答案,还查看了文档说明。

2..mainloop() 是否总是必须在海龟程序的末尾?

3.我以前用过.mainloop()。我的问题是,如果我有 f.f.g 代码:

import turtle

screen = turtle.Screen()
alex =  turtle.Turtle()
tess = turtle.Turtle()

def yes(x, y):
    alex.onclick(yes)
    print("Hello World")

tess.onclick(yes)
turtle.mainloop()

为什么在运行yes() 函数时,alex 会得到一个动作事件?我知道它确实是因为调用了该函数,但实际发生了什么?我的意思是turtle.mainloop()这个语句是在tess被点击之前运行的,并且在事件循环中等待tess的action事件,那么alex的事件在turtle.mainloop()运行之后是如何进入事件循环的呢?

【问题讨论】:

    标签: python user-interface events turtle-graphics event-loop


    【解决方案1】:

    1. .mainloop() 究竟做了什么?

    Turtle 的 mainloop() 调用 tkinter 的 mainloop() 调用 Tk 的 Tk_MainLoop(),这非常简单:

    void
    Tk_MainLoop(void)
    {
        while (Tk_GetNumMainWindows() > 0) {
            Tcl_DoOneEvent(0);
        }
    }
    

    当所有主窗口打开时,它会在无限循环中处理事件,一次一个。处理的事件包括键盘输入、按钮点击、窗口重塑、文件 I/O、网络活动、计时器、显示刷新和任何其他注册的回调。

    可以在 O'Reily 书籍 第 15 章的介绍中找到对 mainloop 的出色的一页描述。MainLoop 剖析 >Steve Lidie 和 Nancy Walsh 的《掌握 Perl/Tk》。尽管这是一本 Perl/Tk 书籍,但有关 mainloop 的信息也适用于 Python。您可以在线找到此材料,但我不会在此处包含链接,因为我不知道哪些在线副本(如果有)是合法发布的。但是您有足够的信息来搜索它。

    2. .mainloop() 是否总是必须在海龟程序的末尾?

    没有。它应该是精心设计的程序的一部分,但不是必需的。大多数独立程序都会包含它(或类似.done().exitonclick() 的名称),因为没有它,图形窗口将在完成时关闭。但在某些情况下,例如。 IDLE 也许,不需要它来保持图形可见。我在初学者的海龟程序中发现的一个常见错误是在调用 mainloop() 之前创建海龟活动的无限循环,然后想知道为什么各种事件不触发。

    如果您打算让 Tk 为您处理键盘、鼠标和计时器事件,那么调用 .mainloop() 是您开始的方式。在大多数 Python/Tk 程序中,它是最后一条语句,但是当所有 Tk 窗口全部关闭时,它之后可能会执行其他代码。

    我们可以将海龟编程看作是为 Tk 的主循环编写插件代码。设置完成后,后续活动将通过我们通过on*() 函数注册的回调函数来完成。

    3.我以前用过mainloop()。我的问题是,如果我有 f.f.g 代码:...为什么 alex 在函数 yes() 运行

    当您的程序运行时,海龟 Alex 和 Tess 在窗口的中心相互堆叠。当您单击这个海龟堆栈时,事件会发送给 Tess,Tess 位于顶部并有一个事件处理程序。在她的事件处理程序中,Tess 在 Alex 上安装了一个事件处理程序。在 Alex 上安装事件处理程序的行为导致 Alex 移动到 Tess 前面,上升到堆栈的顶部。从现在开始,当您单击海龟堆栈时,Alex 将处理这些事件并且它们不再到达 Tess。如果我们给它们不同的颜色和不同的事件处理程序,我们可以清楚地看到这一点:

    import turtle
    
    alex =  turtle.Turtle(shape="turtle")
    alex.color("blue")
    
    tess = turtle.Turtle(shape="turtle")
    tess.color("pink")
    
    def tess_handler(x, y):
        alex.onclick(alex_handler)
        print("Tess clicked")
    
    def alex_handler(x, y):
        print("Alex clicked")
    
    tess.onclick(tess_handler)
    
    turtle.mainloop()
    

    点击海龟栈会产生:

    > python3 test.py
    Tess clicked
    Alex clicked
    Alex clicked
    Alex clicked
    Alex clicked
    Alex clicked
    Alex clicked
    

    您可以将 Alex 和 Tess 移动到窗口中的不同位置,然后单击它们以确认 Alex 在第一次单击 Tess 之前不会开始接收事件。

    【讨论】:

      【解决方案2】:

      所以 mainloop() 是一个无限循环,它基本上会在某个点阻止代码的执行。你调用它一次(而且只有一次)。

      可以这么说:

      while true:
      circle.draw()
      sumden.mainloop()
      print "circle is being drawn"
      time.sleep(0.1)
      

      你永远不会看到输出和打印语句,因为没有循环。

      【讨论】:

      • 也许代码是这样运行的,但我认为这不是它应该被解释的方式。
      • 我知道代码打印语句在您关闭海龟窗口之前不会运行,但这不是我要查找的信息。
      • 抱歉,这没有帮助。也许我没有很好地阅读你的问题。你能解释一下你在找什么吗?