在绘制完成之前关闭Python Turtle时出现tkinter.tclerror
我有一个用Python写的脚本,可以画出科赫雪花。整个过程都很顺利,但如果我在画完之前关闭了图形窗口,就会出现一大堆错误信息,最后一行是:tkinter.tclerror: invalid command name ".38006576"。我觉得这有点像Java中的Swing库里的exit_on_close选项,但这不是默认设置。不过我没有找到Python的turtle库里有类似的选项。有没有什么建议可以避免这个问题呢?
import turtle
import sys
import easygui as eg
def isNum(s):
try:
int(s)
return True
except ValueError:
return False
run = True
while run:
msg = "Input"
title = "Koch snowflake"
fieldNames = ["Length","Depth"]
fieldValues = [] # we start with blanks for the values
fieldValues = eg.multenterbox(msg,title, fieldNames)
a=0
iterations=0
# make sure that none of the fields was left blank
while 1: # do forever, until we find acceptable values and break out
if fieldValues == None:
break
errmsg = ""
# look for errors in the returned values
for i in range(len(fieldNames)):
if fieldValues[i].strip() == "":
errmsg = errmsg + ('"%s" must be filled.\n\n' % fieldNames[i])
elif not (isNum(fieldValues[i].strip())):
errmsg = errmsg + ('"%s" requires a number.\n\n' % fieldNames[i])
if (isNum(fieldValues[1])):
if float(fieldValues[1].strip()) > 13:
errmsg = errmsg + ('Depth cannot be more than 13!')
if errmsg == "":
break # no problems found
else:
# show the box again, with the errmsg as the message
fieldValues = eg.multenterbox(errmsg, title, fieldNames, fieldValues)
#a=float(input("Length: "))
if not fieldValues == None:
if isNum(fieldValues[0]) and isNum(fieldValues[1]):
a=float(fieldValues[0])
iterations=int(fieldValues[1])
else:
sys.exit(0)
#turtle settings
turtle.bgcolor("black")
turtle.reset()
turtle.up()
turtle.setpos(-a*1.5 ,a)
turtle.down()
turtle.delay(0)
turtle.speed(0)
turtle.pencolor("white")
koch_flake = "EJEJE"
for i in range(iterations):
koch_flake = koch_flake.replace("E","EBEJEBE\n")
turtle.down()
for move in koch_flake:
if move == "E":
turtle.forward(a / (3 ** (iterations - 1)))
elif move == "B":
turtle.left(60)
elif move == "J":
turtle.right(120)
turtle.hideturtle()
image = "KochSnowflake.gif"
msg = "Run it again?"
title = "Please Confirm"
if eg.ynbox(msg, title,('Yes', 'No'),image): # show a Continue/Cancel dialog
run = True
else: # user chose Cancel
sys.exit(0)
1 个回答
1
在一个Canvas
对象上画出海龟,这个对象可以让你访问到Tkinter的根窗口。捕捉根窗口的WM_DELETE_WINDOW
事件。当这个事件被捕捉到时,使用del
命令删除海龟对象,这样它就不会再尝试绘图了。控制海龟事件的线程会因为海龟被删除而抛出一个NameError错误。我们要捕捉这个NameError异常并忽略它。
下面是实现这个功能的代码。我测试过了,它可以正常工作,并且不会抛出任何错误:
import turtle
import Tkinter
import sys
import easygui as eg
def isNum(s):
try:
int(s)
return True
except ValueError:
return False
run = True
while run:
msg = "Input"
title = "Koch snowflake"
fieldNames = ["Length","Depth"]
fieldValues = [] # we start with blanks for the values
fieldValues = eg.multenterbox(msg,title, fieldNames)
a=0
iterations=0
# make sure that none of the fields was left blank
while 1: # do forever, until we find acceptable values and break out
if fieldValues == None:
break
errmsg = ""
# look for errors in the returned values
for i in range(len(fieldNames)):
if fieldValues[i].strip() == "":
errmsg = errmsg + ('"%s" must be filled.\n\n' % fieldNames[i])
elif not (isNum(fieldValues[i].strip())):
errmsg = errmsg + ('"%s" requires a number.\n\n' % fieldNames[i])
if (isNum(fieldValues[1])):
if float(fieldValues[1].strip()) > 13:
errmsg = errmsg + ('Depth cannot be more than 13!')
if errmsg == "":
break # no problems found
else:
# show the box again, with the errmsg as the message
fieldValues = eg.multenterbox(errmsg, title, fieldNames, fieldValues)
#a=float(input("Length: "))
if not fieldValues == None:
if isNum(fieldValues[0]) and isNum(fieldValues[1]):
a=float(fieldValues[0])
iterations=int(fieldValues[1])
else:
sys.exit(0)
root = Tkinter.Tk()
cv = turtle.Canvas(root, width=200, height=200)
cv.pack()
screen = turtle.TurtleScreen(cv)
screen.bgcolor("black")
myturtle = turtle.RawTurtle(screen)
def lastAction():
global myturtle
del myturtle
root.destroy()
root.protocol('WM_DELETE_WINDOW', lastAction)
try:
#turtle settings
screen.bgcolor("black")
myturtle.reset()
myturtle.up()
myturtle.setpos(-a*1.5 ,a)
myturtle.down()
turtle.delay(0)
myturtle.speed(0)
myturtle.pencolor("white")
koch_flake = "EJEJE"
for i in range(iterations):
koch_flake = koch_flake.replace("E","EBEJEBE\n")
myturtle.down()
for move in koch_flake:
if move == "E":
myturtle.forward(a / (3 ** (iterations - 1)))
elif move == "B":
myturtle.left(60)
elif move == "J":
myturtle.right(120)
myturtle.hideturtle()
except NameError:
pass
image = "KochSnowflake.gif"
msg = "Run it again?"
title = "Please Confirm"
if eg.ynbox(msg, title,('Yes', 'No'),image): # show a Continue/Cancel dialog
run = True
else: # user chose Cancel
sys.exit(0)