在完成绘制之前关闭python turtle时获取tkinter.tclerror [英] Get tkinter.tclerror when closing python turtle before it finished it's draw

查看:104
本文介绍了在完成绘制之前关闭python turtle时获取tkinter.tclerror的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个绘制科赫雪花的python脚本.一切正常,除非在绘图完成前关闭tutle图形窗口,否则最后一行将出现一个长错误:tkinter.tclerror:无效的命令名称".38006576". 我认为这就像在java.swing中:exit_on_close.这不是默认值.但是我还没有为python turtle找到类似的东西. 有什么建议可以避免这种情况吗?

I have a python script that draws a koch snowflake. Everything works fine, except if I close the tutle graphics window before the drawing finished I get a long error with this as a final line: tkinter.tclerror: invalid command name ".38006576". I think it's like in java.swing: exit_on_close. Which is not the default. However I haven't found something like this for python turtle. Any suggestions how to avoid this?

            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)

推荐答案

将乌龟画在Canvas对象上,您可以从中访问Tkinter根目录. 捕获根的WM_DELETE_WINDOW事件.捕获事件后,请按del乌龟对象,使其无法继续尝试绘制.控制乌龟事件的线程将引发NameError,因为乌龟已被删除.捕获NameError异常并忽略它.

Paint the turtle on a Canvas object from which you can have access to the Tkinter root. Capture the WM_DELETE_WINDOW event of the root. When the event is captured, del the turtle object so that it can't keep trying to draw. The thread controlling the turtle events will throw a NameError because the turtle has been deleted. Catch the NameError exception and ignore it.

这里是执行此操作的代码.我测试过了它可以正常工作没有引发任何错误:

Here's code to do this. I tested it; it works & doesn't thrown any error:

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)

这篇关于在完成绘制之前关闭python turtle时获取tkinter.tclerror的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆