在Spyder上不断出现错误,请告知

2022-04-05 00:00:00 python spyder

问题描述

这是我收到的错误:

invalid command name "1771926755840move"
    while executing
    "1771926755840move"
    ("after" script)
    invalid command name "1771922102464move"
    while executing
    "1771922102464move"
    ("after" script)
    invalid command name "1771947147520move"
    while executing
    "1771947147520move"
    ("after" script)
    Tcl_AsyncDelete: async handler deleted by the wrong thread

以下是我的代码:

from turtle import *
from random import *
from freegames import vector
from playsound import playsound
import winsound
from tkinter import *
from timeit import default_timer as timer
from datetime import timedelta
from threading import Event
"""
def paused():
    Event.wait()
def unpaused():
    Event.release()
"""    
root = Tk()
root.title("OPTIONS")

def stop():
    bye()
    winsound.PlaySound(None, winsound.SND_PURGE)
def gamingarea():
    bird = vector(0, 0)
    balls = []
    winsound.PlaySound('C:/Users/SONY/Desktop/cs.wav', winsound.SND_LOOP + winsound.SND_ASYNC)
    start = timer()
    def tap(x, y):
         lift = vector(0, 30)
         bird.move(lift)
    def inside(point):
        return -200 < point.x < 200 and -200 < point.y < 200
    
    def draw(alive):
        clear()
        goto(bird.x, bird.y)
        if alive:
            dot(20, "green")
        else: 
            dot(20, "red")
            winsound.PlaySound(None, winsound.SND_PURGE)#when bird is red, music stops
            end = timer()
            color("orange")
            write(str(timedelta(seconds=end-start)), align = "center", font=("Comic Sans MS", 20, "normal", "bold"))
        for ball in balls:
            goto(ball.x, ball.y)
            dot(20, "black")
        update()
    def move():
        bird.y -= 5
        for ball in balls:
            ball.x -= 3 
        if randrange(10) == 0:
            y = randrange(-199, 199)
            ball = vector(199, y)
            balls.append(ball)
        while len(balls) > 0 and not inside(balls[0]):
            balls.pop(0)
        if not inside(bird):
            draw(False)
            return 
        for ball in balls:
            if abs(ball - bird) < 15: 
                draw(False)
                return 
        draw(True)
        ontimer(move, 50)
    title("Dodgy Ball")
    setup(420, 420)
    hideturtle()#turtle is hidden
    up() 
    tracer(False)#Used to turn off animations. When false, animations are turned off. It also turns off automatic updates
    onscreenclick(tap)#calling the tap function when touchpad is touched
    move()
    bgcolor("blue")
    done()
startbutton = Button(root, text = "START", padx=100,pady=100, command=gamingarea)
endbutton = Button(root, text = "KILL!", padx=100,pady=100, command=stop)
#pausebutton = Button(root, text = "PAUSE!", padx = 100, pady = 100, command=paused)
#unpausebutton = Button(root, text = "UNPAUSE", padx = 100, pady = 100, command = unpaused)
startbutton.pack()
endbutton.pack()
#pausebutton.pack()
#unpausebutton.pack()
root.mainloop()

PS:这是我和朋友一起设计的游戏

谢谢


解决方案

问题仅在游戏正在运行(鸟是活的)并且您试图杀死游戏时才会出现。

当您按kill it时,它会运行turtle.bye(),这将删除所有对象并移除窗口,但它不会停止仍要运行move()并绘制对象的ontimer()(但它们不再存在,这会给出消息invalid command name "1771926755840move")。

当您按kill it时,它应该设置变量ie。running = False

def stop():
    global running    
    
    running = False

应签入move以停止循环并关闭窗口

    if running:
        # repeate loop and run `move` again
        turtle.ontimer(move, 50)
    else:
        # stop loop and close window
        turtle.bye()
        #winsound.PlaySound(None, winsound.SND_PURGE)

我的减少了模块的版本。

我创建了自己的类vector,所以我不需要freegames,因为我不知道。

我使用datetime而不是timeit是因为end-start可以直接提供timedelta

我注释了winsound,因为它只适用于Windows,但我使用的是Linux

我为pausedunpased添加了代码,它不需要Threading

#from turtle import *   # PEP8: `import *` is not preferred
#from random import *   # PEP8: `import *` is not preferred
#from tkinter import *  # PEP8: `import *` is not preferred

import turtle
import tkinter as tk
import random
import datetime
#import winsound

# --- classes ---

class vector():

    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def move(self, other):
        self.x += other.x
        self.y += other.y 
               
    def __sub__(self, other):
        return vector(self.x - other.x, self.y - other.y)
                
    def __abs__(self):
        return (self.x**2 + self.y**2)**0.5
        
# --- functions ---

def paused():
    global pause
    
    pause = True

def unpaused():
    global pause
    
    pause = False

def stop():
    global running    
    
    if running:
        # stop loop `ontimer(move, 50)`
        running = False
    else:
        # exit when bird is dead
        turtle.bye()
        #winsound.PlaySound(None, winsound.SND_PURGE)
                
def gamingarea():
    global running
    global pause
        
    running = True
    pause   = False

    bird = vector(0, 0)
    balls = []
    #winsound.PlaySound('C:/Users/SONY/Desktop/cs.wav', winsound.SND_LOOP + winsound.SND_ASYNC)
    start = datetime.datetime.now()

    def tap(x, y):
        lift = vector(0, 30)
        bird.move(lift)

    def inside(point):
        return -200 < point.x < 200 and -200 < point.y < 200

    def draw(alive):
        global running
        
        turtle.clear()
        turtle.goto(bird.x, bird.y)
        
        if alive:
            turtle.dot(20, "green")
        else: 
            turtle.dot(20, "red")
            #winsound.PlaySound(None, winsound.SND_PURGE)#when bird is red, music stops
            turtle.color("orange")
            end = datetime.datetime.now()
            diff = end-start
            turtle.write(str(diff.seconds), align = "center", font=("Comic Sans MS", 20, "normal", "bold"))
            running = False
            
        for ball in balls:
            turtle.goto(ball.x, ball.y)
            turtle.dot(20, "black")
            
        turtle.update()

    def move():
        if not pause:
            bird.y -= 5
            
            for ball in balls:
                ball.x -= 3 
                
            if random.randrange(10) == 0:
                y = random.randrange(-199, 199)
                ball = vector(199, y)
                balls.append(ball)
                
            while len(balls) > 0 and not inside(balls[0]):
                balls.pop(0)
                
            if not inside(bird):
                draw(False)
                return 
                
            for ball in balls:
                if abs(ball - bird) < 15: 
                    draw(False)
                    return 
                    
            draw(True)

        if running:
            # repeate loop `ontimer(move, 50)`
            turtle.ontimer(move, 50)
        else:
            # stop loop `ontimer(move, 50)` and exit
            turtle.bye()
            #winsound.PlaySound(None, winsound.SND_PURGE)
                   
    turtle.title("Dodgy Ball")
    turtle.setup(420, 420)
    turtle.hideturtle()  # turtle is hidden
    turtle.up() 
    turtle.tracer(False)  # Used to turn off animations. When false, animations are turned off. It also turns off automatic updates
    turtle.onscreenclick(tap)  # calling the tap function when touchpad is touched
    move()
    turtle.bgcolor("blue")
    turtle.done()

# --- main ---

root = tk.Tk()
root.title("OPTIONS")

start_button = tk.Button(root, text="START", padx=100,pady=100, command=gamingarea)
end_button = tk.Button(root, text="KILL!", padx=100,pady=100, command=stop)
pause_button = tk.Button(root, text="PAUSE!", padx=100, pady=100, command=paused)
unpause_button = tk.Button(root, text="UNPAUSE", padx=100, pady=100, command=unpaused)

start_button.pack(fill='both')
end_button.pack(fill='both')
pause_button.pack(fill='both')
unpause_button.pack(fill='both')

root.mainloop()

坦率地说,如果您使用tkinter to display buttons then you could use tkinter.Canvasto draw objects, andtkinter.bind()to runtap, and root.after()instead ofontimer()to run loop - and then you don't needturtle`

相关文章