Tkinter游戏开发:列表与PhotoImage索引类型异常报错求助
Tkinter Canvas游戏开发中的索引错误排查与解决
我用Tkinter的Canvas组件练手开发小游戏,先创建了一个存储tkinter PhotoImage对象的列表:
# Tiles as Tkinter PhotoImage Classes tiles = [] for i in range(64): tiles.append(tk.PhotoImage(file=os.path.dirname(os.path.realpath(__file__)) + f'\\graphics\\fr{i}.png'))
这是程序里唯一使用PhotoImage的地方。接着我定义了一个处理tiles的类:
# Game Object Class class Object(): def __init__(self, x, y, tag, ani_tiles): self.x = x self.y = y self.tag = tag self.ani_tiles = ani_tiles # 存储动画帧对应的tkinter PhotoImage列表 self.ani_frame = 0 # 绘制精灵 def draw_sprite(self): try: canvas.delete(self.id) except: pass self.id = canvas.create_image(self.x, self.y, image=tiles[self.ani_tiles[self.ani_frame]], tag=self.tag)
之后我这样实例化该类:
cRow = 0 for row in self.screen: cCol = 0 for tile in row: x = (cCol*TILE_RAD*2)+TILE_RAD y = (cRow*TILE_RAD*2)+TILE_RAD+(SCORE_HEIGHT*TILE_RAD*2) Object(x, y, tag='t', ani_tiles=[tile]) cCol += 1 cRow += 1
此时出现错误:
self.id = canvas.create_image(self.x, self.y, image=tiles[self.ani_tiles[0]], tag=self.tag) TypeError: list indices must be integers or slices, not PhotoImage
如果改成这样传参:
Object(x, y, tag='t', ani_tiles=tile)
同时修改Object类中的代码:
self.id = canvas.create_image(self.x, self.y, image=tiles[self.ani_tiles], tag=self.tag)
又会出现另一个错误:
self.id = canvas.create_image(self.x, self.y, image=tiles[self.ani_tiles], tag=self.tag) TypeError: list indices must be integers or slices, not list
完全搞不懂为什么看起来是列表的变量被识别成PhotoImage,看起来是整数的变量又被识别成列表,不知道该怎么排查解决。
问题分析与解决
核心问题出在**tile变量的实际类型和预期不符**,以及对ani_tiles的用途理解错位:
- 第一个错误提示
tiles[self.ani_tiles[0]]的索引是PhotoImage,说明self.ani_tiles[0]本身就是PhotoImage对象,而非你以为的整数索引。这意味着你实例化时传入的[tile]里的tile是PhotoImage,不是整数。 - 第二个错误提示
tiles[self.ani_tiles]的索引是列表,说明你传入的tile其实是个列表,不是整数。
排查与修正步骤:
- 先打印
type(tile)和tile的实际值,确认self.screen中的每个tile到底是整数、列表还是PhotoImage。 - 你的
tiles列表是用整数索引存储PhotoImage的,所以ani_tiles应该是整数索引的列表(对应tiles里的元素):- 如果
self.screen中的tile是0-63之间的整数,保持实例化时传ani_tiles=[tile],类里的draw_sprite方法无需修改,因为self.ani_tiles[self.ani_frame]会取到整数索引,再去tiles中获取对应的PhotoImage。 - 如果
self.screen中的tile已经是PhotoImage对象,那完全不需要通过tiles列表二次索引,直接修改类的draw_sprite方法,直接使用传入的PhotoImage即可:def draw_sprite(self): try: canvas.delete(self.id) except: pass self.id = canvas.create_image(self.x, self.y, image=self.ani_tiles[self.ani_frame], tag=self.tag)
- 如果
内容的提问来源于stack exchange,提问作者Yalc06
相关产品推荐
相关产品推荐

