Skip to main content
 首页 » 编程设计

python之在完成绘制之前关闭 python turtle 时获取 tkinter.tclerror

2025年05月04日10mate10pro

我有一个绘制 koch 雪花的 python 脚本。一切正常,除非我在绘图完成之前关闭 tutle 图形窗口,我得到一个很长的错误,最后一行:tkinter.tclerror:无效的命令名称“.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) 

请您参考如下方法:

在 Canvas 对象上绘制 turtle ,您可以从该对象访问 Tkinter 根。 捕获根的 WM_DELETE_WINDOW 事件。当事件被捕获时,del turtle 对象,这样它就不能继续尝试绘制。控制 turtle 事件的线程将抛出 NameError,因为 turtle 已被删除。捕获 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)