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

标签 python window tkinter exit turtle-graphics

我有一个绘制 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)

关于python - 在完成绘制之前关闭 python turtle 时获取 tkinter.tclerror,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15588583/

相关文章:

Python 一种热向量编码

python - Spotipy 不通过 Oauth 验证?

python - 谁能指出 TG2 相对于 Django 的优缺点?

python - 模拟 tkinter pack 几何形状中的顶部、底部、左侧和右侧边距

python - 为什么 tkinter 不能很好地处理多处理?

python - 如何根据高斯分布制作环

jQuery - 通过从窗口大小中减去像素来计算元素宽度

javascript - 如何动态调整jqgrid到当前窗口大小?

python - 如何在启动对话框时使父窗口不可见

python - 如何将我的 Python 3 应用程序编译为 .exe?