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

如何销毁存储在列表中的Tkinter对象?解决属性错误问题

问题解决思路

错误原因

tkinter.Canvas.create_oval() 返回的是整数类型的图形ID,并非可调用.destroy()的控件对象。你试图对整数调用destroy()方法,自然会抛出AttributeError: 'int' object has no attribute 'destroy'。

可行解决方案

Tkinter画布的图形需要用画布的delete()方法删除,传入图形ID即可彻底移除画布上的图形,后续再从列表中移除对应数据即可。

修正核心代码

修改World类中的killOrganism方法:

def killOrganism(self, *args):
    for loc in sorted(args, reverse=True):
        # 用画布的delete方法删除图形,替换原来的destroy()
        self.delete(self.organTags[loc])
        self.organTags.pop(loc)
        self.organisms.pop(loc)

完整修正代码

from random import choices, randint
import tkinter


class World(tkinter.Canvas):
    def __init__(self, master, size):

        self.xLim = size[0]
        self.yLim = size[1]

        super().__init__(master, width=self.xLim, height=self.yLim, bg='#27c945')
        self.pack()

        self.organisms = []
        self.organTags = []

        self.run()


    def run(self):

        for organism, organTag in zip(self.organisms, self.organTags):
            organism.movement()
            self.move(organTag, organism.xDis, organism.yDis)
            
            if organism.x >= self.xLim - 10 or organism.x <= 10:
                organism.xDis *= -1
            if organism.y >= self.yLim - 10 or organism.y <= 10:
                organism.yDis *= -1
                
        toKill = []
        for loc in range(len(self.organisms)):
            if choices([0, 1], [90, 10])[0] == 1:
                toKill.append(loc)

        self.killOrganism(*toKill)
        self.newOrganism()

        self.after(25, self.run)


    def newOrganism(self):
        new = organism(self.xLim, self.yLim)
        self.organisms.append(new)
        self.organTags.append(self.create_oval(new.x - 10, new.y - 10, new.x + 10, new.y + 10, fill='black'))


    def killOrganism(self, *args):
        for loc in sorted(args, reverse=True):
            # 修正:用delete方法删除画布图形
            self.delete(self.organTags[loc])
            self.organTags.pop(loc)
            self.organisms.pop(loc)
            

class organism():
    def __init__(self, xLim, yLim):
        self.x = randint(10, xLim - 10)
        self.y = randint(10, yLim - 10)

        self.xLim = xLim - 10
        self.yLim = yLim - 10

        self.xDis = randint(-1, 1)
        self.yDis = randint(-1, 1)


    def movement(self):
        if choices((0, 1), [99, 1]) == [1]:
            self.xDis = randint(-3, 3)
            self.yDis = randint(-2, 2)

        self.x += self.xDis
        self.y += self.yDis


worldWidth = 1280
worldLenght = 960
Map = tkinter.Tk()
Map.geometry(str(worldWidth) + 'x' + str(worldLenght))
field = World(Map, (worldWidth, worldLenght))
field.mainloop()

额外优化建议

目前你用两个列表分别存储生物对象和图形ID,容易出现索引同步问题。可以把生物和对应的图形ID封装成一个类,或者用列表存储元组(organism_instance, tag_id),简化管理:

# 示例:改用单个列表存储元组
self.organisms_with_tags = []

# newOrganism中修改:
def newOrganism(self):
    new = organism(self.xLim, self.yLim)
    tag_id = self.create_oval(new.x - 10, new.y - 10, new.x + 10, new.y + 10, fill='black')
    self.organisms_with_tags.append( (new, tag_id) )

# run中遍历修改:
for organism, organTag in self.organisms_with_tags:
    # ... 原有逻辑不变

# killOrganism修改:
def killOrganism(self, *args):
    for loc in sorted(args, reverse=True):
        org, tag_id = self.organisms_with_tags[loc]
        self.delete(tag_id)
        self.organisms_with_tags.pop(loc)

内容的提问来源于stack exchange,提问作者w kooij

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:00:44