需要解包的值超过0(使用tkinter时python坐标变量错误)

1 投票
2 回答
529 浏览
提问于 2025-04-18 04:11

我正在用tkinter制作一个太空入侵者的克隆游戏...

问题是,当我的“子弹”因为到达画布边界而被删除时,出现了一个错误,提示ValueError: Need more than 0 values to unpack on a variable assignment(请继续阅读)。这个错误是为了防止“子弹”一直飞出可见区域...

我在这里发布的代码只是我目前整个游戏代码的一小部分,但这段代码和我在实际项目中用的“子弹”行为代码是完全一样的...

我知道这段代码是可以工作的,而且“子弹”确实会消失,换句话说... 它是有效的,但我在控制台上不断收到这个错误。当我把这个函数和其他9个函数(那些让入侵者发射子弹的)一起使用时,程序开始变得卡顿和出错,过了一会儿就停止工作了...

所以我有点怀疑,导致我的程序崩溃的原因就是这个错误,但我不知道该怎么办。

希望你能帮我解决这个问题。谢谢!

附:请原谅我糟糕的英语水平。

from Tkinter import *
import os

def LoadImage(name):
    rute = os.path.join('Imagenes',name)
    image = PhotoImage(file=rute)
    return image

root=Tk()

DxShot= 0 #Globals of Directions on x and y
DyShot= -3

def PlayWindow():
    root.withdraw()
    VentanaPlay= Toplevel()
    VentanaPlay.title("Kill'em all!'")
    VentanaPlay.resizable(width=NO, height=NO)
    VentanaPlay.geometry("540x540")

    def Shot():
        x,y= CanvPlay.coords(Ship) #This reads the place from where the shot will have to be created
        ShotImage=LoadImage("Shot.gif")
        Shot1=CanvPlay.create_image(x, y-22, image=ShotImage)
        CanvPlay.img=ShotImage
        def ShotMove():
            global DxShot, DyShot
            x1,y1= CanvPlay.coords(Shot1) #here's where I'm getting the error...
            if y1+DyShot<=0:
                CanvPlay.delete(Shot1) #Also, if I use destroy instead of delete it says "destroy() takes exactly 1 argument (2 given)"
                print("Shot deleted")
            CanvPlay.coords(Shot1, x1+DxShot, y1+DyShot)
            CanvPlay.after(3,ShotMove)
        ShotMove()
        VentanaPlay.after(0,ShotMove)

    def Fire(event):
        Shot()

    CanvPlay= Canvas(VentanaPlay, width=540, height=540, bg="white")
    CanvPlay.config(cursor="dotbox")
    CanvPlay.place(x=-1,y=-1)
    CanvPlay.bind("<space>", Fire)
    CanvPlay.focus_set()

    ShipImage= LoadImage("Ship.gif")
    Ship= CanvPlay.create_image(260, 520, image=ShipImage)

    VentanaPlay.mainloop()

Buttun= Button(root, text= "click me", command=PlayWindow)
Buttun.pack()
root.mainloop()

这是我收到的完整错误追踪信息:

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 531, in callit
func(*args)
File "C:/Users/Bryan/Desktop/crap shot", line 28, in ShotMove
x1,y1= CanvPlay.coords(Shot1)
ValueError: need more than 0 values to unpack
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 531, in callit
func(*args)
File "C:/Users/Bryan/Desktop/crap shot", line 28, in ShotMove
x1,y1= CanvPlay.coords(Shot1)
ValueError: need more than 0 values to unpack

2 个回答

0

你需要以某种方式存储一个 Shots(Shot1s)的列表,像你现在这样使用嵌套函数是行不通的。

嵌套函数可能会导致一些混乱的结果,因为 Python 并不会在定义函数时就评估每个变量并存储它,而是在使用时才去访问。所以当你第一次在 Shot() 函数里面调用 ShotMove() 时,解释器会去找一个叫 Shot1 的东西,并且找到了。然而,当你试图把 ShotMove 函数放到 Shot 函数外面去调用时,解释器就找不到任何 Shot1 了(因为它已经不存在了)。我猜那个奇怪的错误(而不是 NameError 或其他错误)可能是因为 Python 在函数最初定义时检查 NameErrors,而不是在每次运行时都检查。

2

根本问题在于,CanvPlay.coords(Shot1) 返回的是一个空列表或者是 None,而你的代码没有准备好处理这种情况。这种情况可能发生在你删除了你想获取坐标的那个项目时。

实际上,你的 ShotMove 函数里有代码会删除这个射击,然后又试图再次移动这个射击。如果你已经删除了这个射击,可能就不需要再用 after 来移动它了。一个简单的解决办法是把你的 ShotMove 函数改成这样:

def ShotMove():
    global DxShot, DyShot
    x1,y1= CanvPlay.coords(Shot1) #here's where I'm getting the error...
    if y1+DyShot<=0:
        CanvPlay.delete(Shot1) 
        print("Shot deleted")
    else:
        CanvPlay.coords(Shot1, x1+DxShot, y1+DyShot)
        CanvPlay.after(3,ShotMove)

你的代码还有另一个问题,就是你调用了 mainloop 多次。一般来说,你应该只调用一次 mainloop。这可能是导致你的程序在几秒钟后变得卡顿和出错的原因之一。

撰写回答