如何销毁存储在列表中的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
相关产品推荐
相关产品推荐

