You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的用途理解错位:

  1. 第一个错误提示tiles[self.ani_tiles[0]]的索引是PhotoImage,说明self.ani_tiles[0]本身就是PhotoImage对象,而非你以为的整数索引。这意味着你实例化时传入的[tile]里的tile是PhotoImage,不是整数。
  2. 第二个错误提示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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:55:26