使用龟模块exitonclick()

时间:2017-01-09 13:09:00

标签: python python-3.x turtle-graphics

我的代码应在第一部分之后关闭turtle.screen,然后启动另一个屏幕并执行第二部分。但它并没有按计划运作。

import turtle

ws = turtle.Screen()
tod_1 = turtle.Turtle()
tod_1.color("red", "green")
tod_1.begin_fill()
for i in range(3):
    tod_1.forward(50)
    tod_1.left(360 / 3)
tod_1.end_fill()
ws.exitonclick()

input("go'press any thing' ")

ws = turtle.Screen()
tod_2 = turtle.Turtle()
tod_2.color("red", "green")
tod_2.begin_fill()
for i in range(6):
    tod_2.forward(50)
    tod_2.left(360 / 6)
tod_2.end_fill()
ws.exitonclick()

第一部分工作正常,但我在输入()之后得到了这个:

go'press any thing' 
Traceback (most recent call last):
  File "test2.py", line 16, in <module>
    tod_2 = turtle.Turtle()
  File "C:\Users\itt\AppData\Local\Programs\Python\Python36-32\lib\turtle.py", line 3816, in __init__
    visible=visible)
  File "C:\Users\itt\AppData\Local\Programs\Python\Python36-32\lib\turtle.py", line 2557, in __init__
    self._update()
  File "C:\Users\itt\AppData\Local\Programs\Python\Python36-32\lib\turtle.py", line 2660, in _update
    self._update_data()
  File "C:\Users\itt\AppData\Local\Programs\Python\Python36-32\lib\turtle.py", line 2646, in _update_data
    self.screen._incrementudc()
  File "C:\Users\itt\AppData\Local\Programs\Python\Python36-32\lib\turtle.py", line 1292, in _incrementudc
    raise Terminator
turtle.Terminator

我尝试使用以下方法清除所有变量:

import sys
sys.modules[__name__].__dict__.clear()

然后再次导入乌龟并做秒。部分,但没有成功。

1 个答案:

答案 0 :(得分:2)

似乎在导入turtle时会创建许多对象,而exitonclick()会删除所有对象 - 不仅仅是Screen()。创建exitonclick()以结束程序。

但您可以使用oscreenclick(function_name)为鼠标单击分配功能,这将清除屏幕并绘制下一个对象。 onscreenclick执行带有两个参数的函数 - click的位置 - 所以函数必须接收这个信息。

import turtle

# --- functions ---

def second(x, y): 
    # clear screen
    tod.reset()

    tod.color("red", "green")
    tod.begin_fill()
    for i in range(6):
        tod.forward(50)
        tod.left(360 / 6)
        tod.end_fill()

    # run another function on click
    #turtle.onscreenclick(third)

    # end program on click 
    turtle.exitonclick()

# --- main ---

tod = turtle.Turtle()

tod.color("red", "green")
tod.begin_fill()
for i in range(3):
    tod.forward(50)
    tod.left(360 / 3)
    tod.end_fill()

# assign function to click on screen
turtle.onscreenclick(second)

# you need it to - it checks if you clicked (and does othere things)
turtle.mainloop()

编辑:如果您必须删除窗口并再次显示,则可以使用tod._screen._root访问使用tkinter的主窗口,并且您可以隐藏/显示它

tod._screen._root.iconify()   # hide
input("Press Enter: ")
tod._screen._root.deiconify() # show again

工作示例:

#!/usr/bin/env python3

import turtle

# --- functions ---

def stop(callback):

    #tod._screen._root.attributes("-topmost", False)

    tod._screen._root.iconify()
    # upper Y in text means that it will be default answer if you press only Enter
    answer = input("Show more images? [Y/n]: ").strip().lower()
    if not answer: # empty string treat as `Y`
        answer = 'y'
    tod._screen._root.deiconify()

    # problem with moving window above other windows
    #tod._screen._root.lift()
    tod._screen._root.attributes("-topmost", True)
    #tod._screen._root.update()

    if answer == 'y':
        callback()
    else:
        #turtle.exitonclick()
        # or
        turtle.bye()

def first(x=0, y=0):
    tod.color("red", "green")
    tod.begin_fill()
    for i in range(3):
        tod.forward(50)
        tod.left(360 / 3)
        tod.end_fill()

    # assign function to click on screen
    turtle.onscreenclick(lambda x,y:stop(second))

def second(x=0, y=0):
    # clear screen
    tod.reset()

    tod.color("red", "green")
    tod.begin_fill()
    for i in range(6):
        tod.forward(50)
        tod.left(360 / 6)
        tod.end_fill()

    # assign function to click on screen
    turtle.onscreenclick(lambda x,y:stop(third))

def third(x=0, y=0):
    # clear screen
    tod.reset()

    tod.color("red", "green")
    tod.begin_fill()
    for i in range(12):
        tod.forward(50)
        tod.left(360 / 12)
        tod.end_fill()

    # end program on click
    turtle.exitonclick()

# --- main ---

tod = turtle.Turtle()

first()

# you need it to - it checks if you clicked (and does othere things)
turtle.mainloop()

但您可以使用input()及其消息框

代替tkinter
answer = tkinter.messagebox.askyesno('More?', "Show more images?")

工作示例:

#!/usr/bin/env python3

import turtle
import tkinter.messagebox

# --- functions ---

def stop(callback):

    answer = tkinter.messagebox.askyesno('More?', "Show more images?")
    print('answer:', answer)

    if answer:
        callback()
    else:
        #turtle.exitonclick()
        # or
        turtle.bye()

def first(x=0, y=0):
    tod.color("red", "green")
    tod.begin_fill()
    for i in range(3):
        tod.forward(50)
        tod.left(360 / 3)
        tod.end_fill()

    # assign function to click on screen
    turtle.onscreenclick(lambda x,y:stop(second))

def second(x=0, y=0):
    # clear screen
    tod.reset()

    tod.color("red", "green")
    tod.begin_fill()
    for i in range(6):
        tod.forward(50)
        tod.left(360 / 6)
        tod.end_fill()

    # assign function to click on screen
    turtle.onscreenclick(lambda x,y:stop(third))

def third(x=0, y=0):
    # clear screen
    tod.reset()

    tod.color("red", "green")
    tod.begin_fill()
    for i in range(12):
        tod.forward(50)
        tod.left(360 / 12)
        tod.end_fill()

    # end program on click
    turtle.exitonclick()

# --- main ---

tod = turtle.Turtle()

first()

# you need it to - it checks if you clicked (and does othere things)
turtle.mainloop()

编辑:我检查了turtle的源代码,似乎可以设置

turtle.TurtleScreen._RUNNING = True

turtle

之后再次运行exitonclick()

使用和不使用turtle.TurtleScreen._RUNNING = True

尝试此代码
import turtle

turtle.goto(0,50)
turtle.exitonclick()

turtle.TurtleScreen._RUNNING = True

turtle.goto(50,150)
turtle.exitonclick()

turtle.TurtleScreen._RUNNING = True

但也许使用更复杂的代码它将无法工作,因为exitonclick()执行其他操作 - 由exitonclick()执行的原始函数

def _destroy(self):
    root = self._root
    if root is _Screen._root:
        Turtle._pen = None
        Turtle._screen = None
        _Screen._root = None
        _Screen._canvas = None
    TurtleScreen._RUNNING = False
    root.destroy()